正規表現の基礎

参考書籍 : 実践bashによるサイバーセキュリティ対策



以下のテキストファイル、frost.txtを使用する

1    Two roads diverged in a yellow wood,
2    And sorry I could not travel both
3    And be one traveler, long I stood
4    And looked down one as far as I could
5    To where it bent in the undergrowth;
6
7 Excerpt from The Road Not Taken by Robert Frost

 


grepの利用
①コマンドオプション
 -c : パターンにマッチした行数を算出する
 -E : 拡張正規表現を有効にする
 -f : 検索するパターンをファイルから読み込む
 -i : 大文字と小文字の区別を無視する
 -l : パターンが見つかったファイル名とパスのみを表示する
 -n : パターンが見つかったファイル中の行数のみを表示する
 -P : Perl形式の正規表現を有効にする
 -R, -r : サブディレクトリ内を再帰的に検索する
②コマンド実行例
grepは次の形式で用いられる

grep オプション パターン ファイル名

/home以下のディレクトリで大文字小文字区別なくpasswordという単語を含むファイルを探すには、以下のようにする。

$ grep -R -i 'password' /home

grepとegrep
grep特殊文字に意味をもたせる場合は。\を付加する
例えば、1かaで始まる行を出力するには、grep '^\(1\|a\)' frost.txtとする必要がある
grep実行時に-Eオプションを指定することで、\なしで特殊文字を使用できる。
egrepはgrepgrep -eとして呼び出すだけのスクリプトである。
拡張正規表現に関連する文字は、? + { | ( )のみ。これらの文字を使うときはgrep -Eかegrepを使う



正規表現のメタ文字
①メタ文字「.」
.(ピリオド)は任意の一文字にマッチする。
T.oというパターンマッチングでは、frost.txtの先頭行がマッチする

$ grep 'T.o' frost.txt
1    Two roads diverged in a yellow wood,

 
②メタ文字「?」
?は直前の要素の0回もしくは1回の繰り返し。egrepで使用する。

$ egrep 'T.?o' frost.txt
1    Two roads diverged in a yellow wood,
5    To where it bent in the undergrowth;

Tから始まり、任意の一文字の0回か1回の繰り返し。
0回も含まれるため、Toもマッチングする。

③メタ文字「*」
アスタリスク(*)は直前の要素の0回もしくは1回”以上”の繰り返しにマッチするメタ文字である。

$ grep -P 'T.*o' frost.txt
1    Two roads diverged in a yellow wood,
5    To where it bent in the undergrowth;
7 Excerpt from The Road Not Taken by Robert Frost

grepはデフォルトで最長一致であるので、Two roads diverged in a yellow wooと、To where it bent in the undergro、The Road Not Taken by Robert Froがマッチする。

④メタ文字「+」

  1. は直前の要素が1回以上の繰り返しとマッチする。
$ egrep 'T.+o' frost.txt
1    Two roads diverged in a yellow wood,
5    To where it bent in the undergrowth;
7 Excerpt from The Road Not Taken by Robert Frost

最低1回以上なので、Toとはマッチしない。
Two roads diverged in a yellow wooと、To where it bent in the undergro、The Road Not Taken by Robert Froがマッチする。

⑤グルーピング
「(」カッコを用いて文字のグルーピングが可能。カッコ内の文字列は一つの要素として扱われる。

$ egrep 'And be one (stranger|traveler), long I stood' frost.txt
3    And be one traveler, long I stood

OR制御子「|」によってグルーピングしたため、travelerがstrangerであっても一致する。

⑥「[」カッコと文字クラス
正規表現に置いて、「{」カッコはクラスの指定だけでなく、マッチする文字集合の指定ができる。
[a-j]でaからjの間の1文字にマッチする。例として
 [abc] : a、b、c、のいずれかにマッチ
 [1-5] : 1~5の数字にマッチ
 [a-zA-Z] : 任意の大文字か小文字のアルファベットにマッチ
 [0-9+-*/] : 数値もしくは4つの数学記号にマッチ
 [0-9a-fA-F] : 16進数の数値にマッチ
ショートカットとして、いくつかの文字クラスが定義されている
 \s : 空白
 \S : 空白以外
 \d : 数値
 \D : 数値以外
 \w : 単語
 \W : 単語以外
 \x : 16進数の数値
これらのショートカットは、grepに-Pオプションを用いる必要がある。
次のように、数値を抽出できる。

$ grep -P '\d' frost.txt
1    Two roads diverged in a yellow wood,
2    And sorry I could not travel both
3    And be one traveler, long I stood
4    And looked down one as far as I could
5    To where it bent in the undergrowth;
6
7 Excerpt from The Road Not Taken by Robert Frost

これら以外にも[:alnum:]など複数の文字クラスがある。
これらのクラスは[内で用いる必要があるため、常に[カッコは二重となる。

$ grep '[[:cntrl:]]' large.date # 制御文字を含む行にマッチする
$ grep 'X[[:upper:][:digit:]]' idlist.txt # Xの後ろに大文字か数字が一文字続く行にマッチする

文字クラスは一文字にしかマッチしないので、必要に応じ*や+を用いる。

⑦後方参照
\1で最初にマッチした(カッコ、\2で次にマッチした(カッコのように、一度マッチした(カッコを省略できる。
次のtags.txtを例にする。

1	Command
2	<i>line</i>
3	is
4	<div>great</div>
5	<u>!</u>

HTMLタグのペアにマッチングした行を抽出するには、後方参照を用いて次のようにする。

$ egrep '<([a-zA-Z]*)>.*</\1>' tags.txt
2       <i>line</i>
4       <div>great</div>
5       <u>!</u>

後方参照により、[a-zA-Z]*がタグにマッチすれば、\1もそのタグと同じパターンを参照することになる。

⑧量指定子
{ }構文により、ある項目が文字列内に繰り返し出現する回数を指定する。
T{5}というパターンは、Tのちょうど5回繰り返しとマッチする。
T{3,6}はTが3回から6回の連続した繰り返し、T{5,}はTの5回以上の連続した繰り返しとマッチする。

⑨アンカーと単語境界
アンカーにより、あるパターンが文字列の先頭または末尾に出現することを指定できる。
例えば、^[1-5]は行の先頭が1から5の数値の行にマッチし、[1-5]$は末尾が1から5の数値の行にマッチする。
単語境界(スペースなど)を示す、\bを用いる事ができる。
例えば、\b[1-5]\bというパターンは、1から5のいずれか一文字で1単語となっているパターンにマッチする。