コマンドの出力にシェルスクリプトの特定の文字列が含まれているかどうかの確認


116

シェルスクリプトを書いていて、コマンドの出力に特定の文字列が含まれているかどうかを確認しようとしています。おそらくgrepを使用する必要があると思いますが、方法がわかりません。誰か知っている?


コマンドは、探している出力文字列を生成した後も実行を続ける必要がありますか、それともその時点ですぐに閉じることができますか?(あなたの2つの答えは、この点でセマンティクスの点で異なります)。
Charles Duffy

回答:


97

grepの戻り値をテストします。

./somecommand | grep 'string' &> /dev/null
if [ $? == 0 ]; then
   echo "matched"
fi

これは次のように慣用的に行われます。

if ./somecommand | grep -q 'string'; then
   echo "matched"
fi

そしてまた:

./somecommand | grep -q 'string' && echo 'matched'

2
このコードは、すべてのPOSIXシェルで機能するわけではありません。POSIX標準は=、比較演算子である必要があるだけで、==; ではありません。pubs.opengroup.org/onlinepubs/9699919799/utilities/test.htmlを
Charles Duffy

4
また、grep 'string' &>/dev/nullPOSIXに準拠しておらず、実行に時間がかかります(string長い出力ストリームの早い段階で表示される場合)grep -q string。[を発行したsomecommand後でも実行を継続したい場合、警告が発生します。stringその場合grep -q、stdinを閉じ、最初のインスタンスが表示された後に終了stringすると、逆効果になります]。(Re:「非POSIX準拠」&>は拡張機能です-POSIXによるリダイレクトのサポートについては、pubs.opengroup.org / onlinepubs / 009695399 / utilities /…を参照してください)。
Charles Duffy

構文の完全な理解を促すために、なぜそれが機能するのか、各パラメータが何をするのかが説明されていれば役立つでしょう
redfox05

157

テスト$?はアンチパターンです

if ./somecommand | grep -q 'string'; then
  echo "matched"
fi

万が一、固定文字列のみをテストする場合は、Fおよびxオプションを追加しますgrep -Fxq 。Fは固定(解釈されない)を表し、xは行全体を表します
Erdal G.

4
なぜテスト$?はアンチパターンですか?
Vitaly Zdanevich 2018年

1
@VitalyZdanevichそれは同時実行性に対して堅牢ではないので、私は仮定します。
Konrad Reiche、2018年

@VitalyZdanevichの1つとして、テストで$?は上記のコマンドをset -eERRトラップの目的で「チェック済み」に設定しないため、後で意図的に偽のパスに戻るだけでプログラムを終了できます。もう1つの$?理由は、揮発性のグローバルな状態です。誤ってその値を破棄するのは簡単です。たとえば、のようなロギングの行を追加するとecho "Exit status is $?"、の新しい値$?がの終了ステータスになりechoます。
Charles Duffy

6

別のオプションは、コマンド出力で正規表現の一致をチェックすることです。

例えば:

[[ "$(./somecommand)" =~ "sub string" ]] && echo "Output includes 'sub string'"

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.