1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

grepコマンドを体系的に学ぶ

Posted at

はじめに

最近実務でgrepコマンドを使う機会が何度かあったのですが、全然使いこなせていないと感じることが多かったので、これを機に体系的に学び直してみました。

対象読者

  • grepコマンドについて知らない、使ったことがない方
  • 業務でたまにgrepコマンドを使うが、その都度オプションなどを調べている方
  • grepコマンドを体系的に学んだことがない方

grepコマンドとは

指定した文字列やパターンに一致する行をディレクトリやファイルから検索するコマンドです。
様々なオプションが用意されていたり正規表現が使えることから、柔軟な検索が可能です。

grepの基本操作

以下が基本文法になります。

$ grep [オプション] 文字列 <検索対象のファイル or ディレクトリ>

指定できるオプション一覧

オプション 説明
-r ディレクトリとその中にあるディレクトリから検索
-v 特定の文字列を除外し検索
-E 拡張正規表現を使い検索
-l 検索結果にファイル名のみ出力
-c 検索で一致した行数を出力
-h 検索結果にファイル名を出力しない
-i 大文字・小文字区別せずに検索
-x 完全一致する行を検索
-n 検索結果に行番号を出力
-o 検索に一致した文字列のみを出力
-w 指定した単語に完全一致する行を検索
-C 検索結果に一致した行とその前後の行を指定した数だけ表示
-A 検索結果に一致した行とその後の行を指定した数だけ出力
-B 検索結果に一致した行とその前の行を指定した数だけ出力
-L 検索に該当しなかったファイルを出力
--exclude="*.拡張子" 特定の拡張子のファイルを検索から除外
--exclude-dir=path 特定のディレクトリを検索から除外
--include="*.拡張子" 特定の拡張子のファイルをのみを検索対象とする

オプションは以下のように複数組み合わせても使えます。

$ grep -nE "user_(path|url)"

# -Eで拡張正規表現を使い検索
# -nで検索結果に行数を出力する


$ grep -rohE "[ぁ-んァ-ン亜-熙 -】]+" ./*

# -rディレクトリの中のディレクトリも検索対象とする
# -oと-hで検索に一致した文字列のみを表示(ファイル名は出力しない)
# -Eで拡張正規表現を使って検索

grepコマンドの使用例

これまで紹介したオプションなどの情報を元に、どのような使用例があるのかを例付きで記載していきます。

(※一部の例では筆者が慣れ親しんでいるRailsのコードを題材とさせていただいております🙏)

指定したファイルから特定の文字を検索

例)ログファイルからERRORを含む行を検索

$ grep "ERROR" development.log

指定したディレクトリから特定の文字を検索

例)usersディレクトリ内のファイルからnameを含む行を検索

$ grep "name" users/*

-rでディレクトリとその中にあるディレクトリから検索

ディレクトリの中にあるディレクトリも検索対象に含めたい場合は、-rオプションをつける必要があります。

例)controllersディレクトリとその中にあるディレクトリからUser.createを含む行を検索

$ grep -r "User.create" app/controllers/*

AND検索

パイプ(|)でgrepを繋げてAND検索が行えます。

例)controllersディレクトリからuserprofileを含む行を検索

$ grep -r "user" app/controllers/* | grep profile

後述する-vオプションと組み合わせることで「ooを含むがooは含まない」といった検索も可能です。

例)ログファイルからstatusを含むかつ200が含まれていない行を検索

$ grep "status" development.log | grep -v 200

OR検索

-eオプションを使うことOR検索が行えます

例)ログファイルからINSERTまたはUPDATEを含む行を検索

$ grep -e "INSERT" -e "UPDATE" development.log

-vで特定の文字列を除外し検索

例)ログファイルからINFOを含まない行を検索

$ grep -v "INFO" development.log

-Eで拡張正規表現を使い検索

拡張正規表現とは基本の正規表現を拡張したものです。
たとえば以下の記法は拡張正規表現に該当します。

  • +:直前の文字の1回以上の繰り返し
  • ?:直前の文字の0回もしくは1回の繰り返し
  • a|b:左右いずれかの文字列

参考

例)左右いずれかの文字列に該当する行を検索

$ grep -E "user_(path|url)"

例)oo(1文字以上のアルファベット)_pathという文字列に該当する行を検索

$ grep -E "[a-zA-Z]+_path"

-lで検索結果にファイル名のみ出力

特定の文字列を含む行があるファイル名のリストを作りたい場合など有効です。

例)-rと組み合わせてcontrollersディレクトリとその中にあるディレクトリからApplicationControllerクラスを継承しているControllerクラスのファイル名を出力

$ grep -rl "< ApplicationController" app/controllers/*

users_controller.rb
posts_controller.rb

-cで検索で一致した行数を出力

例)modelsディレクトリからUser.createを含む行の数をファイルごとに出力する

$ grep -c "User.create" app/models/*

app/models/user.rb:1
app/models/post.rb:2

-hで検索結果にファイル名を出力しない

該当する行だけを表示したい場合は有効です。

例)controllersディレクトリからcreateを含む行を検索し、行のみを出力

$ grep -h "create" app/controllers/*

before_action :create_posts, only: [:create, :update]
def create
  User.create(post_id: @post.id)
def create_posts
  Post.create
def create_profile
  user.create_profile

-iで大文字・小文字区別せず検索

例)ログファイルから大文字小文字区別せずerrorを含む行を検索

$ grep -i "error" development.log

-xで完全一致する行を検索

例えばuseradmin_userの2つが存在し、userのみを検索したい場合などに有効です。

例)modelsディレクトリからuser.update(name: name)に完全一致する行を検索

$ grep -x "user.update(name: name)" app/models/*

-nで検索結果に行番号を出力する

例)modelsディレクトリからUser.createを含む行を検索し行番号付きで出力

$ grep -n "User.create" app/models/*

app/controllers/users_controller.rb:2 before_action :create_posts, only: [:create, :update]
app/controllers/users_controller.rb:11 def create
app/controllers/users_controller.rb:12   User.create(post_id: @post.id)
app/controllers/users_controller.rb:37 def create_posts
app/controllers/users_controller.rb:38   Post.create
user.rb:20 def create_profile
user.rb:21   user.create_profile

-oで検索に一致した文字列のみを出力

正規表現を使って絞り込んだ結果、どのような文字列が該当するのかを確認したい場合に有効です。

1行の中に複数一致する場合、それぞれ一致する文字列を別行で表示します。

$ echo "apple banana apple" | grep -o "apple"

apple
apple

例)ログファイルからどのテーブルに対してSELECT文が発行されているかを出力

$ grep -o "SELECT * FROM [a-zA-Z]" development.log

development.log:SELECT * FROM users;
development.log:SELECT * FROM posts;

-wで指定した単語に完全一致する行を検索

単語として完全一致する行を検索します。
単語の前後が英数字やアンダースコアの場合はマッチしません。

# 以下はマッチする
$ echo "User" | grep -w "User"
$ echo "User.create" | grep -w "User"

# 以下はマッチしない
$ echo "Users" | grep -w "User"
$ echo "User1" | grep -w "User"
$ echo "User_" | grep -w "User"

例)userという単語に一致する行だけを検索する(user_oooo_userなどは除外したい)

grep -w "user" app/models/*

-Cで検索結果に一致した行とその前後の行を指定した数だけ出力

検索行の前後でどのような処理が呼ばれているかを確認したい場合に有効です。

例)user.rbファイルから、Profile.createを含む行を検索し、前後5行を出力

$ grep -C 5 "Profile.create" user.rb

-Aで検索結果に一致した行とその後の行を指定した数だけ出力

検索行の後にどのような処理が呼ばれているかを確認したい場合に有効です。

例)ログファイルでSELECT * FROM users;を含む行を検索し、後の5行を出力

$ grep -A 5 "SELECT * FROM users;" development.log

-Bで検索結果に一致した行とその前の行を指定した数だけ出力

検索行の前でどのような処理が呼ばれているかを確認したい場合に有効です。

例)ログファイルでERRORを含む行を検索し、前の10行を出力

$ grep -B 10 "ERROR" development.log

-Lで検索に該当しなかったファイルを出力

特定の処理を定義できていないファイルを探したい場合など有効です。

例)controllersディレクトリとその中にあるディレクトリからApplicationControllerクラスを継承していないControllerクラスのファイルを出力

$ grep -rL "< ApplicationController" app/controllers/*

特定の拡張子のファイルをのみを検索対象とする

--include="*.<対象としたい拡張子>"とすれば指定した拡張子のファイルだけを検索します。

例)appディレクトリとその中にあるディレクトリかつ、拡張子が.rbのファイルからUserを含む行を検索

$ grep -r "User" app/* --include="*.rb"

特定のディレクトリを検索から除外

--exclude-dir=<除外するディレクトリのパス>とすれば指定したディレクトリ以外で検索します。

例)appディレクトリからviewsディレクトリを除外した上でUserを含む行を検索

$ grep -r "User" app/* --exclude-dir=views

特定の拡張子のファイルを検索から除外

--exclude="*.<除外する拡張子>"とすれば指定したファイル以外で検索します。

例)appディレクトリから拡張子が.htmlのファイルを除外した上でUserを含む行を検索

$ grep -r "User" app/* --exclude="*.html"

おまけ

正規表現を活用した例

これまで紹介したオプションだけでなく、正規表現を使うことでより柔軟な検索が可能です。
以下で正規表現を使用した検索例をいくつか紹介します。

例1)先頭にuser_が付いているメソッドを検索

grep -r "def user_.*" app/*

例2)末尾に_userがついているメソッドを検索

grep -rE "def.*_user$" app/*

例3)メールアドレスらしき文字列を検索

grep -E '[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-z]{2,}'

例4)空白文字で始まる行を検索

grep "^[[:space:]]" template.txt

参考にさせていただいた記事・ドキュメント

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?