よくわからないエンジニア

よく分からないエンジニアの日々の記録

よくわからないエンジニア

grepについて

長らく新規の記事を更新しておりませんでした。正直、若干ブログに飽きた為。
久しぶりにちゃんと更新しようと思います。記事の内容は掲題の通りです。

grepについて調べてみた

お仕事でよくファイル内の文字列を検索する事があります。サーバを複製して設定を一部手動で変更したりするんですが、手書きで変更していると複製前の情報が残ってたりするので、最後の確認で特定ディレクトリに向けて、複製前のサーバ名で検索かけたりします。そんな時私は「grep」コマンドを使っています。

しかし、普段ネット情報見ながら、なんとなくコマンド使っているので、grepのオプションもよく把握してませんでした。疑問を持った時が調べ時、さっそくmanから調べてみました。尚、検索はソースインストールしたapacheのディレクトリの中でやってます。

grepの使い方(オプション)
grep [OPTIONS] PATTERN [FILE...]
grep [OPTIONS] [-e PATTERN | -f FILE] [FILE...]

こちらはmanで確認した使い方です。「test」という文字列を「httpd-vhosts.conf」から探したいという、物凄いシンプルな使い方なら以下でオッケーです。

# grep test httpd-vhosts.conf
    ServerName test.co.jp

該当のファイルから指定した文字列を含む行が表示されます。複数行あれば、その分表示されます。何行目が該当するのか調べたい場合は“-n”オプションをつけます。

# grep -n test httpd-vhosts.conf
25:    ServerName test.co.jp

該当する行の前x行を含んで表示させたければ“-Ax”、該当する行の後x行を含んで表示させたければ“-Bx”、前後の場合は“-Cx”のオプションを使用します。下は全部1行ずつ付与させるパターンです。

# grep -A1 test httpd-vhosts.conf
    ServerName test.co.jp
    DocumentRoot "/usr/local/apache2/htdocs"
# grep -B1 test httpd-vhosts.conf
<VirtualHost  *.*.*.*:80>
    ServerName test.co.jp
# grep -C1 test httpd-vhosts.conf
<VirtualHost  *.*.*.*:80>
    ServerName test.co.jp
    DocumentRoot "/usr/local/apache2/htdocs"

ファイル単品で検索するのはこんな感じですが、実際は一つのファイルに対して検索かける機会より、複数ファイルや特定ディレクトリの配下全体を検索するのに使うのがメインになると思います。ファイルが複数の場合、単純にファイル名を並べてあげればオッケーです。ディレクトリが違ってもフルパスで記述すれば問題なく検索出来ます。

#grep -nA1 test httpd-vhosts.conf extra/httpd-ssl.conf
httpd-vhosts.conf:25:    ServerName test.co.jp
httpd-vhosts.conf-26-    DocumentRoot "/usr/local/apache2/htdocs"
--
extra/httpd-ssl.conf:122:    ServerName test.co.jp
extra/httpd-ssl.conf-123-    DocumentRoot "/usr/local/apache2/htdocs"

ファイル名が特定出来ていれば上記で複数指定すれば良いんですが、そうではなく「特定のディレクトリ以下全てのファイルを対象」とする場合は“-r”のオプションを付与します。このオプションをつければ、再帰的に指定したディレクトリを検索してくれます。grepがBinaryファイルと判断したファイルは「Binary file **** matches」と表示されて、普通に邪魔なので“-I”オプションを付与します。例えば、今いるディレクトリ以下で「test」を含む全てのファイルの行を表示する場合は以下になります。

# grep -rnI test ./
./httpd-vhosts.conf:25:    ServerName test.co.jp
./magic:147:# I didn't have a crunched file handy, so the crunch number is untested.
./magic:282:# There are tests to ascmagic.c to cope with mail and news.
<省略>
./extra/httpd-languages.conf:90:# are good at carefully testing your setup after each change.
./original/extra/httpd-languages.conf:90:# are good at carefully testing your setup after each change.

行数や内容ではなく、対象ファイルだけを抽出したい場合は“-l”オプションを使いましょう。

 grep -rlI test ./
./httpd-vhosts.conf
./magic
./extra/httpd-vhosts.conf
./extra/httpd-languages.conf
./original/extra/httpd-languages.conf
grepでの文字列置換

折角grepで対象ファイルを抽出出来たら、まとめて置換したいですよね。例えば、指定ディレクトリ以下の全てのファイルで"test"という文字列をProductionに変更するコマンドになります。

grep -rlI test ./ |xargs sed -i.bak -e 's/test/production/g'

これで現在のディレクトリ配下のtestという文字列はproductionに変換されます。"-i.bak"は念の為に変換前のファイルを.bak形式でバックアップを取るsedのオプションです。但し、このまま実行すると、本当に対象のファイルが問答無用で置換されるので、予め"-i.bak"のオプションは外した状態で、変換される箇所を確認しておくのが無難でしょう。

grep -rlI test ./ |xargs sed -e 's/test/production/g' |grep production

その他、役に立ちそうなオプションがあったら、適宜追記します。

わかりやすいgrepの使い方は、みんとちゃんに教わって下さい。