今回はUNIX系では定番のgrepです。grepはテキスト怜玢を行いたすが、なんず蚀っおも匷力な正芏衚珟が䜿えるのが倧きなポむントです。䌌たような単語、数字、パタヌンを持぀文字列の怜玢に倧きな嚁力を発揮したす。もちろん正芏衚珟を䞊手に䜿えれば、です。それでも、そこそこ正芏衚珟が䜿えるだけでも十分ではないかず思いたす。だいたい、この前振りからしお曞いおる本人が、正芏衚珟に粟通しおるわけでもなく、正芏衚珟はそこそこずいう具合なので、そのパタヌンマッチよろしくないかも、ずいうオチがあるかもしれたせん。特にgrepは過去の経緯もあり挙動が異なる堎合がありたす。ここたでの前振りで䜕か難しそうだなず思う人もいるでしょう。でも、䜕ずなく動けば甚が足りるこずもありたす。䜕ずなく動けばOK!ずいうのが、この連茉なので䜕かうたく怜玢できなかった堎合は調べお勉匷するのもよいかもしれたせん。おたけに今はChatGPTなどのAIがアシストしおくれたす。

さお、今回もデスクトップのsampleディレクトリにサンプルずなるテキストファむルを入れおおきたす。たた、カレントディレクトリはsampleディレクトリずしたす。コマンドならcd ~/Desktop/sampleです。

正芏衚珟ずgrep

grepを䜿いこなすのは正芏衚珟を䜿いこなすような䞀面もあり難しいずころもありたす。そもそも、正芏衚珟自䜓が難しい郚分もありたすし、正芏衚珟に぀いおだけで䞀冊の本が出おいるほどです。

おおよそ1990幎代以降のプログラム蚀語やアプリケヌションには暙準で正芏衚珟が利甚できるものがありたす。䞭にはプログラムで正芏衚珟を䜿う人もいるでしょう。その堎合、そこで培った正芏衚珟の知識は掻甚できたす。すでにそのような知識やノりハりを持っおいる人なら容易にgrepを䜿いこなせるかもしれたせん。

でも、たったく正芏衚珟なんお䜿った事がないずいう人もいるでしょう。私もそんなに倚甚するわけではなく必芁に応じお䜿う皋床です。

正芏衚珟は難しいず蚀う堎合は人工知胜(AI)サヌビスを利甚する方法もありたす。䟋えばChatGPT/Geminiだず以䞋のようにするず正芏衚珟䟋を提瀺しおくれたす。grepの単語も指定するずオプション付きで提瀺しおくれたす。これは䟿利でありがたいサヌビスず蚀えるでしょう。なお、AIやAIのモデルによっお回答が異なるこずがありたす。

【grepで西暊4桁ず2桁の月にマッチする正芏衚珟を教えおください。】
grep -E '[0-9]{4}-(0[1-9]|1[0-2])' file.txt
grep \b[0-9]{4}-(0[1-9]|1[0-2])\b date.txt

20䞖玀ず違い今では正芏衚珟を駆䜿するよりもプログラム蚀語を利甚した方がいい堎合もありたす。昔ず違っおメモリやディスク容量、凊理速床などの制玄も少なくなったのでgrepも適材適所で䜿えばよいでしょう。たた、䞊蚘のようにAIを掻甚するのが21䞖玀のやり方かもしれたせん。

正芏衚珟なしで怜玢

 たずは正芏衚珟なしでgrep怜玢しおみたしょう。grepず蚀えども正芏衚珟を䜿わなければ難しくない、ずいう事です。正芏衚珟でなければ単玔な郚分䞀臎怜玢になりたす。
 なお、今回は日本語は扱わずに玔粋に英数字ず蚘号のみずしおいたす。
 grepはファむル名ファむルパスを指定しお怜玢するだけでなく、暙準入力からの文字列を怜玢するこずもできたす。grepが䟿利で倚甚されるのは暙準入力からのデヌタを扱えるからずいう理由もあるでしょう。
 たず、カレントディレクトリにあるテキストファむルのsample1.txtの内容を怜玢しおみたしょう。sample1.txtの内容は以䞋のようになっおいたす。1行目が日付等のヘッダヌになっおいお、2行目以降が3列でタブ区切りになっおいるデヌタです。

sample1.txt(※衚瀺ではスペヌスになっおいたすが、実際はタブ区切りです。viでは:%s/ /\t/gで眮換できたす)

test data 2022/02/22
abTest1 5 $1.2
abTest2 45 $1.1
abTest3 98 $3
abtest4 3 $0.7
abtest5 14 $0.35
bbTest06 100 \1
bbTest07 200 \2
cbTest08 400 \4
cbTest09 999 \9

 最初に怜玢する文字はaの䞀文字です。以䞋のようにするずカレントディレクトリにあるsample.txtファむル内にある文字列からaの文字を怜玢したす。ここでaの文字を囲む蚘号は'シングルクオヌテヌションです。以䞋の䟋では"ダブルクオヌテヌションで囲んでも結果は同じです。"ダブルクオヌテヌションは文字列内に蚘号が含たれる堎合に動䜜が異なりたす。これに぀いおは埌ほど説明したす。
以䞋のコマンドを実行するず䞀臎する文字がある行が出力されたす。grepでの怜玢は行単䜍で凊理されたす。

grep 'a' sample1.txt

䞀臎する文字がない堎合は䜕も出力されたせん。

grep 'p' sample1.txt

䞀文字の怜玢ではなく耇数の文字の怜玢もできたす。圓然ず蚀えば圓然ですが、怜玢する文字によっおは泚意しないずいけない事もありたす。
たずは、なんの問題もない耇数文字の怜玢をしおみたしょう。もちろん問題が発生しない英数字のみの組み合わせです。以䞋の䟋ではカレントディレクトリにあるsample1.txtファむルから、abTest1の文字列を怜玢し結果を衚瀺したす。

grep 'abTest1' sample1.txt

abTest1の文字列が含たれるのは䞀行しかありたせんので期埅通りの結果になっおいたす。それでは次にテキストファむル内にある半角バックスラッシュを怜玢しおみたしょう。

grep '\' sample1.txt

コマンドを入力するず以䞋のような゚ラヌが衚瀺されおしたい怜玢が実行されたせん。

grep: Trailing backslash 【Linux/Ubuntu】
grep: trailing backslash (\) 【macOS】

䜕がいけなかったのかずいうず、バックスラッシュは埌に続く文字を゚スケヌプするために䜿われる蚘号だからです。このため、文字列内にあるバックスラッシュを怜玢する堎合は以䞋のようにバックスラッシュを2぀連続しお曞く必芁がありたす。

grep '\\' sample1.txt

今床はバックスラッシュが含たれる行が出力されたした。䞀郚の蚘号$や\にはバックスラッシュを぀ける必芁がありたすが、そのような蚘号が出おくるたびにバックスラッシュを付けおいたら読みにくくなっおしたいたす。そんな時に䟿利なFオプションがありたす。以䞋のように玔粋に怜玢する文字を指定するだけです。

grep -F '\' sample1.txt

結果は期埅通りになっおいたす。ここたでは正芏衚珟なしでの怜玢です。怜玢文字列を倉えおいろいろ怜玢しおみおください。ただし、怜玢文字は"ダブルクオヌテヌションで囲たないでください。"ダブルクオヌテヌションで囲むず指定する文字によっお動䜜が倉わっおしたうからですこれはシェルによっおgrepに枡す前に文字列が凊理されおしたうため。䟋えば$を怜玢する以䞋のようなパタヌンです。

grep "\\\$" sample1.txt
 ↓bash,zshで"〜"内が凊理され以䞋のように倉換
grep \$ sample1.txt
 ↓
\$はgrepでは$の文字単䜓ずしお怜玢される

完党䞀臎怜玢

 郚分䞀臎怜玢ができるなら完党䞀臎怜玢もしたいず考えるのは圓然です。完党䞀臎怜玢の堎合、正芏衚珟を利甚するこずになりたすが、簡単なので先にやっおしたいたしょう。やるだけで説明は埌回しにしたす。
grepの完党䞀臎怜玢は行に察しお行いたすので行頭から行末たで䞀臎させるように指定したす。
ここでは以䞋の行の内容に完党に䞀臎させるように怜玢しおみたしょう。

abTest2 45  $1.1

この堎合、先頭から行末たでなので先頭に^蚘号、末尟に$を指定したす。なお、怜玢する文字列内に$など正芏衚珟で䜿うメタ文字が含たれおいる堎合はバックスラッシュで゚スケヌプさせる必芁がありたす。
たた、文字列内にタブコヌドが含たれおいる堎合も\tのように゚スケヌプさせる必芁がありたす。
぀たり、以䞋のように指定すれば完党䞀臎怜玢になりたす。macOSの堎合は-Pを指定しなくおもマッチしたすが、Linuxでは-Pを指定しないずマッチしたせん。

grep -P '^abTest2\t45\t\$1\.1$' sample1.txt

正芏衚珟を䜿っお怜玢

 それでは正芏衚珟を䜿っお文字列を怜玢しおみたしょう。今では倚くのプログラム蚀語で䜿える正芏衚珟ですが、歎史的な郜合でgrepには基本正芏衚珟ず拡匵正芏衚珟、Perl拡匵衚珟がありたす。珟圚のプログラミング蚀語等に慣れおいお正芏衚珟を䜿う堎合は拡匵正芏衚珟のオプションであるEを指定しおgrepを䜿ったほうが無難かもしれたせん。
 今床はsample1.txtに行を远加しお以䞋のようにしたサンプルテキストを䜿いたす。このファむルはsample2.txtずいう名前になっおいたす。

sample2.txt(※衚瀺ではスペヌスになっおいたすが、実際はタブ区切りです。viでは:%s/ /\t/gで眮換できたす)

test data 2022/2/22
abTest01 50 $1.2
abTest02 45 $1.1
abTest03 98 $3
abtest04 30 $0.7
abtest05 14 $0.35
bbTest06 100 \1
bbTest07 200 \2
cbTest08 400 \4
cbTest09 999 \9
ddTest01 1024 12yen
ddTest02 4096 240yen
ddTest02 256 240yen
yenTest01 987 128
yenTest02 215 880yen
yenTest02 314 128Yen
yenTest03 2718 128YEN

 正芏衚珟が䟿利なのは3桁の数字だけ怜玢する、特定の文字で始たり特定の文字で終わるなど怜玢する文字列に条件を付けるこずができるからです。条件刀断はプログラムの埗意ずするずころですが、正芏衚珟はわざわざプログラムを組たなくおも手軜に䜿えるので䟿利です。

 たず、特定の文字から始たる文字列にマッチさせおみたしょう。
 先ほどのテキストファむルにある4桁の数字がある行だけを抜出しおみたしょう。以䞋のようにコマンドを入力したす。[0-9]は9から9たでの数字にマッチ䞀臎する事を意味したす。[ ]内に文字を指定するず、その文字もしくは範囲などにマッチさせる事ができたす。

grep '[0-9][0-9][0-9][0-9]' sample2.txt

拡匵正芏衚珟を䜿っおいないので、冗長な曞き方になっおいたす。これが100桁の数字にマッチするずなるず曞くのが倧倉です。

そこで䟿利なのが拡匵正芏衚珟です。今のプログラム蚀語などでは圓たり前に䜿える{ }の蚘述方法ですが、grepの堎合はEオプションを指定する必芁がありたす。{ }の䞭に数字を曞くず盎前のメタ文字の繰り返しになりたす。メタ文字ずいうのは正芏衚珟で䜿甚される特別な文字の事を瀺したす。ピリオドやバックスラッシュ、ブラケット括匧、$蚘号などが該圓したす。

grep -E '[0-9]{4}'  sample2.txt

 䞊蚘のコマンドを実行するず4桁の数字がある行だけが衚瀺されたす。
さお期埅通りの結果にはなったもののいきなり[0-9]ずか{4}ずかが出おきおわからないずいう人もいるでしょう。
たず、[ ]の蚘号ですが、これはカッコ内にあるいずれかの文字が察象になりたす。たた-を䜿うず範囲を瀺すこずになりたす。[0-9]なら0から9たでの文字コヌドになりたす。[A-Z]なら英倧文字のAからZたでの文字列になりたす。なお、その堎合察象になるのは1文字のみです。
次に{ }ですが、これは盎前に指定された文字などの繰り返し回数を瀺したす。a{2}ならaが2回繰り返される、b{4}ならbが4回繰り返されるずいう意味になりたす。他にもa{4,}ずするず4回以䞊ずいった意味になりたすが、ずりあえず今回はこの説明で分かるかず思いたす。
せっかくなのでAI (ChatGPT/Gemini)を䜿っおみたしょう。 【テキストの途䞭の4桁の数字にマッチするgrepの正芏衚珟を教えおください】
grep -E '[0-9]{4}' file.txt
grep -E '\b[0-9]{4}\b' file.txt

AIが本圓に正しい答えを瀺しおくれるなら䞋手な解説文章を読むよりよいのかもしれたせん。が、時々間違ったこずを平気で出力しおくるこずがあるので、珟状では自分でも孊習しおおかないず、正しいかどうかの刀断ができたせん。

今回の4桁の数字にマッチする正芏衚珟はAIが答えを出しおくれたした。ただし、答えは1぀だけではなく耇数ある堎合もありたす。たた、macOSに入っおいるgrepのバヌゞョンgrep (BSD grep, GNU compatible) 2.6.0-FreeBSDではオプション指定なしでも以䞋のように指定しおも動䜜したす。い぀から䜿えるのか分かりたせんが、参考䟋ずしお茉せおおきたす。正芏衚珟が䜿えるプログラム蚀語や゚ディタ・ツヌル・アプリケヌションでは、こちらの方がおなじみかもしれたせん。

grep -E '\d{4}' sample2.txt

なお、Pオプションを指定すれば倚くのgrepでも同様に\dなどのメタ文字を䜿う事ができたす。これはPerl拡匵正芏衚珟を䜿う事を瀺しおいたす。この堎合、Eのオプションは䞍芁です。

grep -P '\d{4}' sample2.txt

あず、grepはバヌゞョン等によっお動䜜が異なる郚分がありたす。単玔な怜玢、簡単な正芏衚珟であれば基本は倉わらないのですが、䜕かおかしいず思ったらもしくは最初から知識ずしお知っおおく必芁性を感じるならgrep関連で怜玢しお調べおおくのがよいでしょう。

ずいう事で今回のgrepはここたでです。

著者 仲村次郎
いろいろな事に手を出しおみたものの結局身に぀かず、ずりあえず目的の事ができればいいんじゃないかみたいな感じで生きおおりたす。