正規表現入門
途中に混ざっているものまで拾ってしまう
バックアップを除いた設定ファイルの一覧が欲しいとします。
ターミナル
$ cat /tmp/paths.txt
app.conf
app.conf.bak
db.conf
notes.txt
$ grep conf /tmp/paths.txt
app.conf
app.conf.bak
db.confapp.conf.bak まで付いてきました。conf という並びが行のどこかにあれば一致するので、途中に含まれているだけの行も残ります。
欲しいのは「conf で終わる行」です。末尾に $ を書くと、行の終わりという位置を指せます。
ターミナル
$ grep 'conf$' /tmp/paths.txt
app.conf
db.conf$ は文字ではなく位置です。conf$ は「conf という並びのすぐ後ろが行末である」という条件になります。
位置を指せると嬉しいのは、「含まれている」ことと「そこで終わる」ことが別だからです。ファイル名でも、行頭に日付が出るログでも、位置まで決めないと似たものが混ざります。まず語だけで引いてみて、多すぎたら位置を足す、という順で組み立ててください。
行の先頭でも同じことをしたい
先頭の位置を指すのが ^ です。
ターミナル
$ grep '^db' /tmp/paths.txt
db.conf^ と $ を両方書けば、行全体を条件にできます。間に何も挟まない ^$ は「行頭のすぐ後ろが行末」、つまり空行だけに一致します。
^ や $ のように、文字そのものではなく条件を表す記号をメタ文字と呼びます。メタ文字を組み合わせて文字列の形を表す書き方が正規表現で、grep はその形に合う行を選んでいます。
この書き方が通じるのは grep の中だけではありません。このあと出てくる sed も awk も、行を選ぶところで同じ正規表現を読みます。ここで覚えた ^ と $ は、そのまま持ち越せます。
クォートを外すとシェルに食われる
正規表現はシングルクォートで囲みます。
ターミナル
$ grep '^db' /tmp/paths.txt
db.conf囲まないと、grep に届く前にシェルが記号を解釈してしまうことがあります。$ はシェルにとって変数の始まりで、* はファイル名の展開です。クォートで囲めば、書いたままの文字列が grep に渡ります。
二重引用符では
$の解釈が残ります。正規表現を囲むのはシングルクォートと決めておくと事故が減ります。
課題
- echo でテストデータを作る
- grep でアンカー ^ を使う
- apple と ant の 2 行だけ出力する