【シェルスクリプト】grepで文字列を抽出する方法!正規表現も使用します

教師

シェルスクリプトのgrepのやり方がよくわかりません。オプションや正規表現を使用した文字列抽出を行いたいです。

そういった声が多いので今回はシェルスクリプトのgrepについて教えます!

現役エンジニアの筆者もよく使用するので、実例などを用いて教示します。

windowsのプロンプトで使用できるbatやpythonやphpを使用して、業務効率化やアプリやWebサイトを作成しております。javaやシェルスクリプトなど、様々なプログラミングを行った実績ありの筆者です。

shellscriptのgrepを使用して文字列を抽出する方法はよく使います。シェルスクリプトを使用するなら必須の項目です。

・・・・・
目次

シェルスクリプトでgrepの使い方の基本

code

シェルスクリプトでgrepの使い方の基本

シェルスクリプトでのgrepは検索したい文字列を、指定したファイルから行全体を抽出します。

またデフォルトでは基本正規表現を使用するので、拡張正規表現を使用したい場合はオプションをつけます。

正規表現、grepのオプションについては後の項目で学習します。

検索文字列は大文字小文字を区別します。

grepの使い方の基本

シェルスクリプトでgrepの使い方の基本構文は以下です。

grep 検索文字列 検索ファイル(パス付き)

検索ファイルについては複数指定できます。半角スペースを区切りにしてファイルを指定していきます。

grep 検索文字列 検索ファイル1 検索ファイル2 . . .

実践:grepの基本

では実際にgrepを使用して文字列を抽出してみます。

grep root /etc/passwd

「root」という文字列を「/etc/passwd」のファイルから抽出しています。

このシェルスクリプトを実行してみます。

root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin

「/etc/passwd」のファイルで「root」が含まれる行全体が2行抽出されました。

今度は検索するファイルを複数にしてみます。

grep root /etc/passwd /etc/group

「root」という文字列を「/etc/passwd」と「/etc/group」のファイルから抽出しています。

このシェルスクリプトを実行してみます。

/etc/passwd:root:x:0:0:root:/root:/bin/bash
/etc/passwd:operator:x:11:0:operator:/root:/sbin/nologin
/etc/group:root:x:0:

「/etc/passwd」と「/etc/group」で「root」が含まれる行全体がファイル名付きで抽出されました。

複数のファイルを指定した場合は「ファイル名:対象の行」が表示されます。

grepの検索オプションについて

パソコン教室

シェルスクリプトでgrepのオプションについて

grepの検索オプションについてまとめます。

オプション効果
-E拡張正規表現を使用
-F正規表現を使用しない
-i大文字小文字を区別しない
-e検索文字列を指定する
-v検索結果を反転させる
シェルスクリプトでgrepのオプション一覧

拡張正規表現を使用したい時につけるのが「-E」オプションです。

シェルスクリプトの基本でデフォルトは基本正規表現を使用すると説明しました。拡張正規表現を使用したい時につけるのが「-E」オプションです。

正規表現を使用した検索は、後の項目で説明します。

正規表現を使用したくない場合には「-F」オプションを使用します。

正規表現を使用した検索は、後の項目で説明します。

検索文字列の大文字小文字を区別したくない場合は「-i」オプションを使用します。

echo オプションなし
grep Root /etc/passwd
echo オプションあり
grep -i Root /etc/passwd

-iオプションを使用する時としない時のシェルスクリプトを実行してみます。

オプションなし
オプションあり
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin

オプションなしの場合Rootの大文字小文字が区別される為、何も表示されません。逆にオプションありの場合はrootが含まれる行が表示されました。

-iオプションで大文字小文字が区別されないので正解です。

検索文字列を指定する場合は「-e」オプションを使います。主に検索文字列を複数指定したい場合に使用します。

まずエラーが出るシェルスクリプトを実行してみます。

grep root postfix /etc/passwd

例えば複数の文字列を含むものを抽出したい時に、上のシェルスクリプトを実行してみます。

grep: postfix: そのようなファイルやディレクトリはありません
/etc/passwd:root:x:0:0:root:/root:/bin/bash
/etc/passwd:operator:x:11:0:operator:/root:/sbin/nologin

上のような実行結果となりエラーが出ました。

エラーの原因として「root」を含む文字列を「postfix」と「/etc/passwd」のファイルから抽出するシェルスクリプトと認識されているからです。

「postfix」というファイルがないとみなされエラーが出てきます。「/etc/passwd」には「root」があるので表示されています。

ファイル名も表示されているので、複数のファイルが指定されている動きなのがわかります。

エラーの解決法として-eオプションがあります。「postfix」は検索文字列と明示的に指定できます。

grep -e root -e postfix /etc/passwd

このシェルスクリプトのように検索文字列ごとに「-e」オプションを使います。

root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
postfix:x:89:89::/var/spool/postfix:/sbin/nologin

「/etc/passwd」ファイルの中の「root」と「postfix」の文字列が含まれる行が表示されました。

ファイル名が表示されていないので、単体のファイルが指定されている動きなのがわかります。

指定した文字列が抽出されて、エラーが出ていないので成功です。

指定した結果を反転させるには「-v」オプションを使用します。

「/etc/passwd」から「root」がない行を表示させるシェルスクリプトです。

grep -v root /etc/passwd | head -n 5

「|」はgrepの結果を「|」の後のコマンドの引数にする事が出来るパイプというものです。「head -n 5」は頭から5行だけ表示するコマンドです。

「/etc/passwd」から「root」がない行は多いので5行だけ表示しています。

bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync

「/etc/passwd」から「root」がない行の先頭5行だけ表示されました。

grepの出力オプションについて

code

シェルスクリプトでgrepの出力オプションについて

grepの出力に関するオプションについてまとめます。

出力オプション出力効果
-n抽出された行番号を表示
-H抽出されたファイルのファイル名も表示する
-h抽出されたファイルのファイル名は表示しない
-l抽出されたファイルのファイル名のみ表示する
-L抽出されていないファイル名のみ表示する
-o抽出された箇所のみ表示する
-q抽出された箇所を表示しない
シェルスクリプトでgrepの出力オプション一覧

抽出された行番号を表示したい場合は「-n」オプションを使用します。

抽出した文字列がファイルの何行目にあるかを表示したい事はよくあります。

grep -n root /etc/passwd

「/etc/passwd」から「root」がある行を行番号付きで表示します。

1:root:x:0:0:root:/root:/bin/bash
10:operator:x:11:0:operator:/root:/sbin/nologin

1行目と10行目に「root」がある事がわかります。

抽出されたファイルのファイル名も表示する場合は「-H」オプションを使用します。

抽出されたファイルのファイル名も表示したい場合です。

grep -H root /etc/passwd

「/etc/passwd」から「root」がある行をファイル名付きで表示します。

/etc/passwd:root:x:0:0:root:/root:/bin/bash
/etc/passwd:operator:x:11:0:operator:/root:/sbin/nologin

「root」があるファイル名「/etc/passwd」付で行が表示されました。

抽出されたファイルのファイル名は表示しない場合は「-h」オプションを使用します。

抽出されたファイルのファイル名は表示しない場合です。

grep -h root /etc/passwd /etc/group

複数のファイルを指定すればファイル名が表示されますが、不要な場合に使用します。

root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
root:x:0:

ファイル名が表示されていない事がわかります。

抽出されたファイルのファイル名のみ表示する場合は「-l」オプションを使用します。

抽出されたファイルのファイル名のみ表示するしたい場合があります。

grep -l root /etc/passwd /etc/group

「-l」オプションを使用します。

/etc/passwd
/etc/group

ファイル名のみ表示されている事がわかります。

抽出されていないファイル名のみ表示する場合は「-L」オプションを使用します。

抽出されていないファイル名のみ表示する場合です。

grep -L root /etc/passwd /etc/group /etc/nsswitch.conf

指定した3ファイルの中で「root」が一つもないファイル名を表示するシェルスクリプトです。

/etc/nsswitch.conf

「root」が一つもないファイル名のみ表示されている事がわかります。

抽出された箇所のみ表示する場合は「-o」オプションを使用します。

抽出された箇所のみ表示する場合です。

echo '複数ファイルの場合'
grep -o root /etc/passwd /etc/group
echo '単体ファイルの場合'
grep -o root /etc/passwd

複数ファイルの場合と単体ファイルの場合で表示してみます。

複数ファイルの場合
/etc/passwd:root
/etc/passwd:root
/etc/passwd:root
/etc/passwd:root
/etc/group:root
単体ファイルの場合
root
root
root
root

ファイルの中に「root」がある数だけ表示されている事がわかります。

このシェルスクリプトは、後述する正規表現を含んだ検索で稀に使用します。

抽出された箇所を表示しない場合は「-q」オプションを使用します。

抽出された箇所を表示しない場合です。

grep -q root /etc/passwd /etc/group

指定したファイルの中に「root」があってもなくても表示しないシェルスクリプトです。

実行しても特になにも表示されません。文字列が存在する時としない時の違いは終了ステータスの違いです。

文字列が1つでも存在すれば終了ステータスは「正常」、しなければ「異常」となります。

文字列の存在可否だけが必要で、表示は不要な場合に使用されます。例えば「if」などの判定に「-q」オプションは使用します。

grepで正規表現を使用する

code

シェルスクリプトでgrepの正規表現

grepでの正規表現についてまとめます。正規表現には基本正規表現と拡張正規表現があります。

基本的には拡張正規表現を使用していれば問題ありません。

正規表現で文字列を指定する特別な文字をメタ文字と言います。メタ文字がキーとなります。メタ文字とその効果をまとめます。

シェルスクリプトのgrepで使用するメタ文字の種類
  • 文字を指定するメタ文字
  • 繰り返しを意味するメタ文字
  • 補助的メタ文字
基本正規表現メタ文字拡張正規表現メタ文字効果
..何かしらの1文字
^^最初の文字
$$最後の文字
[][]限定文字指定
[^][^]限定文字以外
シェルスクリプトで使用できる正規表現一覧

何かしらの文字列を抽出する場合は「.」を使用します。

何かしらの文字列を抽出する場合です。

grep 'roo.' /etc/passwd

指定したファイルの中に「roo」と何らかの1文字の文字列があれば抽出します。

「’」で文字列を囲わなくても抽出できますが、エラーになる指定の仕方もあるので、全て「’」で囲う事を推奨します。

root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin

「roo」と何らかの文字の「t」が結合された「root」が抽出されました。

最初の文字列を指定するには「^」を使用します。

最初の文字列を指定する場合です。

grep '^root' /etc/passwd

指定したファイルの中で「root」から始まる行を抽出します。

root:x:0:0:root:/root:/bin/bash

「root」から始まる行のみが抽出されました。

最後の文字を指定するには「$」を使用します。

最後の文字を指定する場合です。

grep 'nologin$' /etc/passwd | head -n 3

指定したファイルの中で「nologin」で終わる行を抽出します。

grepの基本で前述しましたが「| head -n 3」はgrepの結果の頭3行のみを抽出するコマンドです。

bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin

「nologin」で終わる行のみが抽出されました。

限定文字を指定するには[]を使用します。

限定文字を指定する場合です。

grep 'roo[stu]' /etc/passwd

指定したファイルの中で「roo」とあと「s」か「t」か「u」かで組み合わせる文字列があれば抽出します。

root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin

「root」が含まれる行が抽出されました。

grep 'roo[s-u]' /etc/passwd

続き文字列であれば上のように指定もできます。数字であれば[1-3]のようにも指定できます。

限定文字以外を指定するには[^]を使用します。

限定文字以外を指定する場合です。

grep 'roo[^abc]' /etc/passwd 

指定したファイルの中で「roo」とあと「a」か「b」か「c」以外の文字で組み合わせる文字列があれば抽出します。

root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin

「root」が含まれる行が抽出されました。

次は繰り返しのメタ文字をまとめます。

基本正規表現メタ文字拡張正規表現メタ文字効果
**直前の文字の0回以上の繰り返し
無し+直前の文字の1回以上の繰り返し
無し?直前の文字の0回もしくは1回の繰り返し
\{m\}{m}直前の文字のm回の繰り返し
\{m,\}{m,}直前の文字のm回以上の繰り返し
\{m,n\}{m,n}直前の文字のm回以上n回以下の繰り返し
シェルスクリプトで使用できる繰り返しの正規表現一覧

直前の文字の0回以上の繰り返しするには「*」を使用します。

直前の文字の0回以上の繰り返しする場合です。拡張正規表現の場合は「-E」オプションを使用します。

echo 基本正規表現
grep 'roo*t' /etc/passwd
echo 拡張正規表現
grep -E 'roo*t' /etc/passwd

指定したファイルの中で「ro」とその後に「o」の0回以上の繰り返しがあり、その後に「t」が来る文字列を抽出します。「rot」や「root」や「rooot」などが抽出されます。

基本正規表現
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
拡張正規表現
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin

どちらも「root」が含まれる行が抽出されました。

基本か拡張かどちらを使用する方が良いかですが、拡張の方を使用する事を推奨します。

直前の文字の1回以上の繰り返しするには「+」を使用します。

直前の文字の1回以上の繰り返しする場合です。拡張正規表現のみ使用できます。

echo 基本正規表現
grep 'roo+t' /etc/passwd
echo 拡張正規表現
grep -E 'roo+t' /etc/passwd

指定したファイルの中で「ro」とその後に「o」の1回以上の繰り返しがあり、その後に「t」が来る文字列を抽出します。「root」や「rooot」などが抽出されます。今回「rot」などは非対象ですね。

基本正規表現
拡張正規表現
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin

基本正規表現は対応していないので抽出されず、拡張の方は「root」が含まれる行が抽出されました。

直前の文字の0回もしくは1回の繰り返しするには「?」を使用します。

直前の文字の0回もしくは1回の繰り返しする場合です。拡張正規表現のみ使用できます。

echo 基本正規表現
grep 'ro?t' /etc/passwd
echo 拡張正規表現1
grep -E 'ro?t' /etc/passwd
echo 拡張正規表現2
grep -E 'roo?t' /etc/passwd
echo 拡張正規表現3
grep -E 'rooo?t' /etc/passwd

指定したファイルの中で「r」、「ro」、「roo」とその後に「o」の0回か1回の繰り返しがあり、その後に「t」が来る文字列を抽出しまみます。

基本正規表現
拡張正規表現1
rtkit:x:172:172:RealtimeKit:/proc:/sbin/nologin
拡張正規表現2
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
拡張正規表現3
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin

拡張1は「rt」と「rot」、拡張2は「rot」と「root」、拡張3は「root」と「rooot」が抽出されます。

基本正規表現は対応していないので抽出されず、拡張1は「rt」が拡張2と3は「root」が含まれる行が抽出されました。

直前の文字のm回の繰り返しするには{m}を使用します。

直前の文字の繰り返し回数を指定する場合です。基本正規表現を使用したい場合は「{」や「}」の前に「\」を付けます。

echo 基本正規表現
grep 'ro\{2\}t' /etc/passwd
echo 拡張正規表現
grep -E 'ro{2}t' /etc/passwd

指定したファイルの中で「ro」とその後に「o」の2回のみの繰り返しがあり、その後に「t」が来る文字列を抽出します。「root」が抽出されます。「rooot」や「roooot」などは非対象ですね。

基本正規表現
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
拡張正規表現
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin

どちらも「root」が含まれる行が抽出されました。

直前の文字のm回以上の繰り返しするには{m,}を使用します。

直前の文字の繰り返し回数以上を指定する場合です。基本正規表現を使用したい場合は「{」や「}」の前に「\」を付けます。

echo 基本正規表現
grep 'ro\{2,\}t' /etc/passwd
echo 拡張正規表現
grep -E 'ro{2,}t' /etc/passwd

指定したファイルの中で「ro」とその後に「o」の2回以上の繰り返しがあり、その後に「t」が来る文字列を抽出します。「root」や「rooot」や「roooot」などが抽出されます。

基本正規表現
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
拡張正規表現
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin

どちらも「root」が含まれる行が抽出されました。

直前の文字のm回以上n回以下の繰り返しするには{m,n}を使用します。

直前の文字の繰り返し回数以上と以下を指定する場合です。基本正規表現を使用したい場合は「{」や「}」の前に「\」を付けます。

echo 基本正規表現
grep 'ro\{2,3\}t' /etc/passwd
echo 拡張正規表現
grep -E 'ro{2,3}t' /etc/passwd

指定したファイルの中で「ro」とその後に「o」の2回以上3回以下の繰り返しがあり、その後に「t」が来る文字列を抽出します。「root」や「rooot」が抽出されます。「roooot」などは対象外ですね。

基本正規表現
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
拡張正規表現
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin

どちらも「root」が含まれる行が抽出されました。

最後に補助的なメタ文字をご紹介します。

文字列指定の補助的なメタ文字をまとめます。

基本正規表現メタ文字拡張正規表現メタ文字効果
\\直後のメタ文字を普通の文字として扱う
\(\)()指定する文字列をクループ化する
無し|複数の正規表現をORで繋げる
シェルスクリプトで使用できる補助的正規表現一覧

補助的なメタ文字を試すにあたり環境を説明します。シェルスクリプトと同階層に「5_grep」というディレクトリがあり、その配下に「grep_test.txt」があるとします。

「grep_test.txt」の内容は以下とします。

ro\{2\}t
root
abcc
abcbc
abcbcbc
123
12323
1232323
123123123
12333
abcabcabc

直後のメタ文字を普通の文字として扱うには「\」を使用します。

直後のメタ文字を普通の文字として扱う場合です。基本正規表現と拡張正規表現とどちらも使用できます。

echo 基本正規表現1 繰り返し
grep 'ro\{2\}t' 5_grep/grep_test.txt

echo 基本正規表現2 直後のメタ文字を普通の文字として扱う
grep 'ro\\{2\\}t' 5_grep/grep_test.txt

echo 拡張正規表現1 繰り返し
grep -E 'ro\{2\}t' 5_grep/grep_test.txt

echo 拡張正規表現2 直後のメタ文字を普通の文字として扱う
grep -E 'ro\\{2\\}t' 5_grep/grep_test.txt

指定したファイルの中で「ro\{2\}t」という文字列を抽出したいです。しかし「ro\{2\}t」は繰り返しで出てきたoを2回繰り返すメタ文字です。

このままでは「root」が抽出されるので「\」を「\」で普通の文字列にエスケープします。これで「ro\{2\}t」という文字列が抽出できます。

拡張正規表現においては「ro\{2\}t」の「\」はメタ文字と解釈されているので何も表示されません。

同じく「ro\{2\}t」の「\」を「\」で普通の文字列にエスケープします。これで拡張正規表現の方も「ro\{2\}t」という文字列が抽出できます。

基本正規表現1
root
基本正規表現2
ro\{2\}t
拡張正規表現1
拡張正規表現2
ro\{2\}t

どちらも「ro\\{2\\}t」とすることで「ro\{2\}t」という文字列が抽出されました。

指定する文字列をクループ化して扱うには()を使用します。

指定する文字列をクループ化して扱う場合です。基本正規表現と拡張正規表現とどちらも使用できます。

echo 基本正規表現1 単体文字繰り返し
grep 'abc\{2\}' 5_grep/grep_test.txt

echo 基本正規表現2 グループで繰り返し
grep 'a\(bc\)\{2\}' 5_grep/grep_test.txt

echo 拡張正規表現1 単体文字繰り返し
grep -E 'abc{2}' 5_grep/grep_test.txt

echo 拡張正規表現2 グループで繰り返し
grep -E 'a(bc){2}' 5_grep/grep_test.txt

基本正規表現1は指定したファイルの中で「abc」の一つ前の「c」を2回繰り返すというシェルスクリプトでした。しかし「bc」の繰り返しにしたい場合は、基本正規表現2のように該当文字列を\(\)で囲いグループ化します。

拡張正規表現1も同様です。「bc」の繰り返しにしたい場合は、拡張正規表現2のように該当文字列を()で囲いグループ化します。

基本正規表現1
abcc
基本正規表現2
abcbc
abcbcbc
拡張正規表現1
abcc
拡張正規表現2
abcbc
abcbcbc

どちらも「a」とその後に「bc」が2回以上繰り返す文字列が抽出されました。

複数の正規表現をORで繋げるには「|」を使用します。

複数の正規表現をORで繋げる場合です。拡張正規表現しか対応していません。

指定したファイルの中で「abc」か「123」という文字列を抽出したいです。

echo 拡張正規表現1
grep -E 'abc|123' 5_grep/grep_test.txt

「abc|123」で可能です。シェルスクリプトを実行します。

abcc
abcbc
abcbcbc
123
12323
1232323
123123123
12333
abcabcabc

指定したファイルの中で「abc」か「123」という文字列を含む行が抽出されました。

training

ではここで質問です。

したのシェルスクリプトを実行すると取得できる文字列は何になるでしょうか?

grep -E ‘abc|123{3}’ 5_grep/grep_test.txt
abcc
abcbc
abcbcbc
12333
abcabcabc
grep -E ‘abc|(123){3}’ 5_grep/grep_test.txt
abcc
abcbc
abcbcbc
123123123
abcabcabc
grep -E ‘(abc|123){3}’ 5_grep/grep_test.txt
123123123
abcabcabc
管理人

シェルスクリプトのgrepは非常によく使用するので、このページを何度も読んで是非マスターしてください。

教師

この記事が気に入ったら
フォローしてね!

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次