シェルスクリプトで役立つテキスト文字列のパターンマッチングの基礎Beginner's Guide(3/5 ページ)

» 2009年01月06日 14時46分 公開
[Peter Seebach,SourceForge.JP Magazine]
SourceForge.JP Magazine

キャラクタクラス

 h?lloというパターンに潜んでいる2つ目の問題は、その一致範囲が広すぎるというものだ。先に触れたような、正規の英語に比して多少変則的なつづりのスペルも受け付けるようにしておくという配慮はその種のユーザーから歓迎されるだろうが、hzllo、h!llo、hXlloなどは明らかに除外すべきであろう。そうしたより一致範囲の狭いマッチングをシェルで実行するために用意されているのが、キャラクタクラス(character class)という機構だ。

 1つのキャラクタクラスに一致するのは指定範囲内にあるキャラクタの1つだけであり、これは?に一定の制限を設けた機構だと考えてもいいだろう。キャラクタクラスの指定は角カッコ([])で囲むことで行え、具体的には[characters]といった記述をする。例えばここでの例として用いたあいさつ文に対するマッチングについてはh[aeu]lloという1つのキャラクタクラスにまとめることができるのだ。なおキャラクタクラスのマッチングにて一致するのは、指定したキャラクタ群のいずれか1つだけであり、これらキャラクタの複数個に一致するという判定はされない。

 キャラクタクラスの一般的な用途は、特定範囲内のキャラクタを指定するという使い方である。実際、任意の数値を対象としたマッチングには[0-9]という指定がよく用いられる。このように2つのキャラクタをハイフンでつないだものは、これらを両端とするキャラクタセット全体を意味する指定だと解釈されるので、その用途としては順番的に連続した並びのアルファベットや数値を示す目的で使われるのが一般的だ。ただしこのパターンでは大文字と小文字が区別されるので、ASCIIの標準アルファベットすべてを指定するのであれば[a-zA-Z]という指定をしなくてはならない。また範囲を特定する2つのキャラクタを前後逆に指定すると、実際にどのようなマッチングが実行されるか予測不能となるので、そうした指定を行うべきではない。

 また“何を含めるか”ではなく“何を除外するか”が分かっている場合は、キャラクタクラスを反転させる記号として、その先頭キャラクタに感嘆符(!)をつければいい。例えば[!0-9]というキャラクタクラスは、数字でない任意のキャラクタに一致する。ただしキャラクタクラスの反転は、通常使われるアルファベット以外の記号類にも一致範囲を広げてしまう点に注意が必要で、仮に子音だけに一致させるつもりで[!aeiou]という指定をすると、句読点や制御記号なども含めることになってしまう。

 またキャラクタクラス中でワイルドカードを利用することはできず、例えば[?*]という指定は、疑問符かアスタリスクのいずれかに一致するだけになる。

 こうしたキャラクタクラスは、シェルで用いるパターンマッチングのうち最も複雑な部類に属すもので、特に左右の角カッコ([])、ハイフン(-)、感嘆符(!)は、キャラクタクラスで意味をなす特殊記号である。また通常の文字としてのハイフン記号そのものをクラスに含めたい場合は、キャラクタクラスの末尾に位置するキャラクタとして指定すればよく(その後には何のキャラクタも続けない)、同じく感嘆符についても、キャラクタクラスの先頭以外であれば任意の場所に配置すればいい(2番目以降に置くべきキャラクタが存在しない場合は、そもそもキャラクタクラスを使う必要性がないので、目的となるキャラクタを単独で指定するべきである)。

 同様の規則は左側の角カッコの場合も当てはまり、これは任意の場所に配置しておけばいいが、右側の角カッコ(])については、リストの先頭キャラクタとするか、あるいはクラスを反転させる!の直後にのみ置くことだけが可能であり、それ以外の場所に右角カッコが配置されていると、それをシェルはキャラクタクラスの終了部を示す記号だと判断するかもしれない。またこうした機能セットに潜む単純なバグとして、シェルによってはキャラクタクラスにおける右角カッコの判定が正常に行われないこともあるので、そのような現象に遭遇した場合は可能な限り使用を避けるべきである。

 具体例として“ほかのキャラクタはすべて除き、左右の角カッコ、ハイフン、感嘆符のいずれかのみに一致させたい”という場合は後記のように指定すればいい。


[][!-]

 このうち1番目の左角カッコはキャラクタクラスの開始を示す記号だが、同じく1番目の右角カッコはキャラクタクラスの終了を示す記号ではなく、対応する角カッコのペア間に何も置かれていないため、通常の文字としての角カッコと見なされる。そして2番目の左角カッコと感嘆符も、その置かれた位置は任意キャラクタを配置する場所であるため、特殊な意味を有す記号とは見なされない。その次にあるハイフンも通常の文字としてのハイフンと見なされるが、それは末尾に位置する2番目の右角カッコは当該キャラクタクラスの終了を示す記号と判定されるため、このハイフンはほかの2つのキャラクタを挟む位置に置かれていないからである。

 なおシェル内で使用するキャラクタクラスにかんしては、キャレット(^)を!の代わりに使用するユーザーも多い。これはすべてのシェルにて採用された移植性のある表記法ではないが、正規表現で使われる記号と共通しているため、多くのシェルが1つの拡張としてこの記号の使用を許可している。いずれにせよこうした使用法もあることを知っておかないと、通常の文字としてのキャレットをキャラクタクラスでマッチングさせようとする場合に、想定外の結果が返されるかもしれない。

 表2-1には、キャラクタクラスで使われる特殊記号および、それらを通常文字として認識させる記述法がまとめてある。

キャラクタ 意味 移植性 通常文字としての記述法
] キャラクタクラスの終了 汎用 キャラクタクラスの先頭に置く(あるいは反転指定記号の直後)
[ キャラクタクラスの開始 汎用 キャラクタクラス中の任意の位置に置く
^ 反転の指定 一般的 ほかのキャラクタの次に置く
! 反転の指定 汎用 ほかのキャラクタの次に置く
- 範囲の指定 汎用 キャラクタクラスの先頭または末尾に置く
表2-1 キャラクタクラスで使われる特殊記号

新しいことをはじめる前には「Beginner's Guide」で知識を得てみませんか?


Copyright © 2010 OSDN Corporation, All Rights Reserved.

注目のテーマ