grepコマンドと正規表現によるファイル内検索
次に、指定したファイルの中から検索文字列を含んでいる行を抽出するgrepコマンドを説明します。
viでも/や?で検索できましたが、あくまでviの機能ですので、viでファイルを開いているときにしか使えません。grepコマンドはviで開かなくても使えることはもちろんのこと、柔軟で多彩な検索が行えるため非常によく使われます。
ここでは検索対象ファイルとして、先ほど作成したtest.txtファイルを使います。viで編集して、内容を次のように変更しておいてください。
abcdef 123456 12ab34 ab56cd
grepの基本
ではさっそく、grepコマンドを使ってみましょう。構文は次のとおりです。
grep '検索文字列' 検索ファイル名
grepコマンドを実行すると、検索ファイルから検索文字列を検索し、マッチした行を表示します。例えば、test.txtファイルに対し「ab」という文字列をgrepで検索すると、次のようになります。
# grep 'ab' test.txt abcdef 12ab34 ab56cd
test.txtから「ab」を含んでいる行が抽出されました。
その文字を含む/その文字以外の文字を含む行の検索
grepの優れているところは、検索文字列に正規表現を使用できるところです。正規表現では、例えば「数字3桁が含まれている文字列」や「aから始まる文字列」というような文字列の構成パターンを記述できます。grepはこの文字列の構成パターンを条件として、検索を行うことができるのです。
次に示すのは、[34ef]という正規表現を使ってtest.txtを検索する例です。[34ef]という正規表現は、「3、4、e、fのいずれか1文字が含まれている」という文字列の構成パターンを表します。
# grep '[34ef]' test.txt abcdef 123456 12ab34
一方で、検索条件にマッチしない「ab56cd」の行は表示されていません。
大括弧[ ]は、「その中に記入されたいずれかの文字を含む」というパターンを表します。「いずれかの数字1文字を含む」というパターンは[0-9]と書けます。grepコマンドでの検索例を見てみましょう。
# grep '[0-9]' test.txt 123456 12ab34 ab56cd
[ ]の中では、半角マイナスを使って「この文字からこの文字までのいずれかの1文字」というパターンを記述できます。上記の場合は「0から9まで(=数値)」ということになります。そのため、アルファベットしかないだけ行は表示されていません。
いずれか1文字とは逆に、「これらの文字以外の1文字」というパターンも[ ]を使って記述できます。[ ]の中の先頭に^(キャレット)を置きます。次の検索例を見てください。
# grep '[^0-9]' test.txt abcdef 12ab34 ab56cd
0から9までの文字以外の文字が入っている行が抽出されています。数字しかない「123456」の行は抽出されていません。
検索位置の指定(行の先頭/末尾)
検索ではよく、「行の先頭が○○」「行の末尾が△△」という条件を使います。grepコマンドの正規表現では、行の先頭を^(キャレット)、行の末尾を$(ドル記号)で表します。^は、先ほど[ ]での検索でも使いましたが意味が異なります。
検索例を見てみましょう。次のgrepコマンドで指定されている正規表現^[0-9]は、「行の先頭が数字1文字」という検索条件を表しています。
# grep '^[0-9]' test.txt 123456 12ab34
一方、次のgrepコマンドで指定されている正規表現[0-9]$は、「行の末尾が数字1文字」という検索条件を表しています。
# grep '[0-9]$' test.txt 123456 12ab34
正規表現は組み合わせて使うこともできます。例えば、「行の先頭が数字以外の文字」という正規表現は^[^0-9]と書けます。
# grep '^[^0-9]' test.txt abcdef ab56cd
直線の文字の繰り返し回数を指定する正規表現
正規表現で{ }記号を使うと、その直前にある文字の繰り返し回数を指定できます。例えば、[0-9]{6}という正規表現は「6桁の数字を含む(数字が6回続けて出現する)」という行にマッチします。
ただし、{ }はgrepコマンドの基本正規表現では対応していません。拡張正規表現に当たります。-Eオプションを指定するとgrepコマンドの正規表現で使うことができます。
# grep -E '[0-9]{6}' test.txt
123456
grepコマンドのバリエーション
-Eオプション付きのgrepコマンドと同じ動きをするコマンドとして、egrepコマンドがあります。上記のgrepコマンドはegrepコマンドを使うと次のように書けます。
# egrep '[0-9]{6}' test.txt
逆に、正規表現を一切使わないgrepコマンドもあります。fgrepです。正規表現に使われる^や$、[ ]などの記号を通常の文字列として検索したい場合にはfgrepコマンドを使いましょう。
sedコマンドによる正規表現を使った文字列の置換
grepコマンドは正規表現を利用して文字列を検索できました。ここで紹介するsedコマンドは、正規表現により検索しマッチした文字列を置換できるコマンドです。sedコマンドの基本構文は次のとおりです。
sed -e "s/置換前文字列/置換後文字列/g" 対象ファイル
具体例を見てみましょう。次のsedコマンドは、数字(0~9)をすべて「N」に置換しています。
# sed -e "s/[0-9]/N/g" test.txt abcdef NNNNNN NNabNN abNNcd
注意点として、sedコマンドはtest.txtの内容を読み出し、s/[0-9]/N/gという指定に従って置換を実行しましたが、test.txtの内容を書き換えたわけではありません。置換した結果が画面に表示されるのみです。
もう1つ、sedコマンドの実行例を見てみましょう。
# sed -E "s/^[a-z]+//g" test.txt 123456 12ab34 56cd
+は「直前にある文字が1文字以降ある」というパターンを表します。ここでは[a-z]の直後にあるので、「aからzまでの文字が1文字以上ある」というパターンになります。+は拡張正規表現に含まれるので、grepコマンドと同じく-Eオプションを指定しています。
また、このsedコマンドでは置換後文字列が何もありません。この場合、置換前文字列のパターンにマッチした部分は削除されることになります。つまり、aからzまで(つまり小文字のアルファベット)が1文字以上並んでいる部分を削除する、という置換が行われます。
このように、正規表現を使うことでより、複雑な文字列の検索や置換が行えるようになります。考え方に馴染むまで難しいのですが、LPIC受験対策に限らず、現場でも便利この上ないものです。grepコマンドとsedコマンドの使い方と合わせてしっかりマスターしましょう。

