grep
新卒エンジニア
新卒

研修でgrepコマンドを使ってみました


grepコマンドとは

grepコマンドとは、ファイル中の探したい文字を検索するのに役に立つコマンドです。

検索パターンには、"検索したい文字"のようにダブルクオーテーションで囲んで検索するほか、正規表現を用いた検索も可能です。


コマンドの使い方

コマンドの書式は以下のようになります。

grep [オプション] パターン [ファイル1 [ファイル2...]]

基本的な使い方は以下になります。

grep "検索したい文字" 検索したいファイル名

検索したいファイルの中に、検索したい文字があるのか調べたい時に使えます。

例えばこのようなファイルがあったとします。


student.txt 

Aida Nozomu

相田 望
Inoue Karen
井上 カレン
Uchida Hiroshi
内田 弘
Uchiyama Gorira
内山 ゴリラ
Enomoto Ren
榎本 蓮
Okabe Misuzu
岡部 美鈴

「内」がつく人を探したいとします。

(Macのターミナルを使って検索しています)

$ grep "内" student.txt

内田 弘
内山 ゴリラ

簡単ですね。このように取り出すことができます。


オプションを使ってみよう

grepコマンドにはオプションがあります。その中のいくつかを紹介します。


特定の文字以外を検索したい

こういう時は-vオプションがオススメです。

-vオプションは、マッチしない行を出力してくれます。

例として、「内」がつかない文字列を検索してみます。

$grep -v "内" student.txt

Aida Nozomu
相田 望
Inoue Karen
井上 カレン
Uchiyama Renzou
Uchida Hiroshi
Uchiyama Gorira
Enomoto Ren
榎本 蓮
Okabe Misuzu
岡部 美鈴

内田 弘と内山 ゴリラが排除されました。

grepコマンドは、指定された文字列が含まれる行を返します

なので、内田 弘というように単語の間に空白があっても、同じ行にあった弘も同じく今回は排除されています。


複数ファイル検索

ファイルが多く、どのファイルに検索したい文字が書いてあるのかわからない時に役に立ちます。

以下のような構造を例にして説明します。

Qiita/

├ fruits.txt
├ teacher.txt
├ student.txt
├ hoge/
└ hoge.txt


fruits.txt

Apple

りんご
Orange
オレンジ
Lemon
レモン


teacher.txt

Uchihara Marina

内原 まりな
Kakimoto Mikan
柿本 みかん
Sasaki Mika
佐々木 ミカ
Seo Hayami
瀬尾 早見


hoge/hoge.txt

Uchiyama

りんご
フルーツ
Apple
内容は適当です

複数のファイルから「内」が含まれるファイルを検索したいと思います。

$grep "内" ./*

grep: ./hoge: Is a directory
./sutudent.txt:内山 廉造
./sutudent.txt:内田 弘
./sutudent.txt:内山 ゴリラ
./teacher.txt:内原 まりな

この検索方法では、カレントディレクトリの下にあるファイルは検索できても、hogeディレクトリは検索できません。hoge/hoge.txtには「内」の文字があるので検索ヒットしてほしいです。

そういう時に便利なのが、-rオプションです。

このオプションは、フォルダ内のファイルを再帰的に検索してくれます。

$grep -r "内" ./*

./hoge/hoge.txt:内容は適当です
./sutudent.txt:内山 廉造
./sutudent.txt:内田 弘
./sutudent.txt:内山 ゴリラ
./teacher.txt:内原 まりな

hogeフォルダの中のファイルも検索してくれました。


ファイル名を一覧で出して欲しい

こんな時は、-lオプションが便利です。

-lオプションは、行の内容は出力しません。マッチしたファイル名を出力してくれます。

ファイルの中身は見えなくてもよく、とにかくファイル名を知りたい時に使えます。

$grep -lr "内" ./*

./hoge/hoge.txt
./sutudent.txt
./teacher.txt


終わりに

例えば、「内」という文字以外かつ"Uchi"も含まないファイルを出力して欲しい場合、

$grep -v "内" | grep -v "Uchi" student.txt

Aida Nozomu
相田 望
Inoue Karen
井上 カレン
内山 廉造
内田 弘
内山 ゴリラ
Enomoto Ren
榎本 蓮
Okabe Misuzu
岡部 美鈴

という結果になってしまいます。

期待値としては、「内」と「Uchi」以外が出力されて欲しかったのですが、うまくいきません。

アドバイスいただけますと幸いです。

以上、研修でgrepコマンドを使ってみました、でした!


追記

アドバイスをいただき、ようやく解決できました!

$grep -v "内" | grep -v "Uchi" student.txt

これは最初に私が試したものです。何が悪いのかというと、 "内" が検索されていないことでした。

もし同じような書き方をするのであれば、

$ grep -v "内" student.txt | grep -v "Uchi"

とすべきだったのです。

パイプラインは、左から見てその結果を右に渡して行きます。

ですので、最初の書き方ですと”内”を除けということは指示してあるのですが、「え?何から探すの??」状態になってしまっていたと思われます。

まずはこのstudent.txtから "内" を除いてねという指示をした後に、プラス "Uchi" も除いてねとするのが正しかったのですね。

しかし、こんな書き方よりも便利な書き方を教えていただきました!

それは、 -eオプションです。


-eオプションとは?

grepで、複数の文字列を指定する際に便利なオプションです。

書き方は以下になります。

$ grep -v -e "内" -e "Uchi" student.txt

grep一つで良いですし、パイプラインで繋げずに済みました。

student.txtから "内" と "Uchi" を除いてねという内容になります。

大変勉強になりました。ありがとうございました!