一致しない場合にgrepが終了しないようにする


29

このスクリプトは「後」をエコーし​​ません。

#!/bin/bash -e

echo "before"

echo "anything" | grep e # it would if I searched for 'y' instead

echo "after"
exit

また-e、shebang行のオプションを削除した場合も同様ですが、エラーが発生した場合にスクリプトが停止するように、それを保持したいです。grepが一致しないことをエラーと見なすことはありません。突然終了するのを防ぐにはどうすればよいですか?


これは考察のみを目的とした観察です。おそらく、このスクリプトのロジックをもう一度考え直すべきです。文字列を見つけることが重要でない場合、なぜそれを検索するのですか?grepの定義では、文字列の有無に基づいて決定を下します。どちらの方法でも構わない場合、それは重要ではありません。また、-eあなたが気にすることを前提としているように思われます:どんな問題でも壊滅的であるように。
アンドリューファラン

2
@AndrewFalanga私は実際にその内容var=$(complex command | grep complex_pattern)がnull である可能性がある(この場合、私のプログラムは終了すべきではない)を分析しているので、どちらの方法でもかまいません。これは、問題を発生させる要約されたスクリプトです。ここには論理に形而上学的なブラックホールはありませんか?;)
iago-lito

出力をキャプチャすることを意図していることがわかったので、いくつかのことが明らかになりました。提示されたように、それは私を混乱させました。
アンドリューファランガ

回答:


33
echo "anything" | grep e || true

説明:

$ echo "anything" | grep e
### error
$ echo $?
1
$ echo "anything" | grep e || true
### no error
$ echo $?
0
### DopeGhoti's "no-op" version
### (Potentially avoids spawning a process, if `true` is not a builtin):
$ echo "anything" | grep e || :
### no error
$ echo $?
0

「||」「または」を意味します。コマンドの最初の部分が「失敗」(「grep e」がゼロ以外の終了コードを返す)の場合、「||」の後の部分 実行され、成功し、終了コードとしてゼロを返します(true常にゼロを返します)。


3
起動しない同じものの少し短いバージョンは、/bin/true次のとおりです command || :(したがって、あなたの場合、set -e; grep 'needle' haystack || :)。
DopeGhoti

1
@DopeGhotiは、true内蔵されている(少なくとも上のいくつかのシェルにbash 4.3RHEL上)
iruvar

3
最初のコマンドが失敗するとエラーが隠されるため、無効です。パイプ内の最初のコマンドが失敗した場合、正しいソリューションはゼロ以外を返します。
ソリン

11

安全かつオプションで grepメッセージを送信する堅牢な方法:

echo something | grep e || [[ $? == 1 ]] ## print 'something', $? is 0
echo something | grep x || [[ $? == 1 ]] ## no output, $? is 0
echo something | grep --wrong-arg e || [[ $? == 1 ]] ## stderr output, $? is 1

posixマニュアルによると、終了コード1 は行が選択されていないことを意味し、> 1はエラーを意味します。


1
これは、grepが何も検出しない場合に警告終了コード(1)のみを抑制するが、真のエラー(終了コード> 1)を渡すため、受け入れられる答えでなければなりません。ここでの他の解決策は、通常は真ではないエラーを常に抑制します。
HaroldFinch

7

別のオプションは、別のコマンドをパイプラインに追加することです-失敗しないもの:

echo "anything" | grep e | cat

catこれはパイプラインの最後のコマンドであるため、パイプラインが失敗したかどうかを判断するために使用されるのcatgrep、のではなくの終了ステータスです。



3

溶液

#!/bin/bash -e

echo "before"

echo "anything" | grep e || : # it would if I searched for 'y' instead

echo "after"
exit

説明

set -e または set -o errexit

パイプライン(単一の単純なコマンドで構成されている場合があります)、リスト、または複合コマンドSHELL GRAMMAR上記を参照)がゼロ以外のステータスで終了した場合、すぐに終了します。失敗するコマンドが、whileor untilキーワードの直後のコマンドリストの一部、ifまたはelif予約語の後に続くテストの一部、final またはに続くコマンドを除く&&or ||リストで 実行されるコマンドの一部である場合、シェルは終了しませんパイプライン内の最後のコマンド、またはコマンドの戻り値が&&||!。サブシェル以外の複合コマンド-eが、無視されている間にコマンドが失敗したためにゼロ以外のステータスを返す場合、シェルは終了しません。上のトラップはERR、設定されている場合、シェルが終了する前に実行されます。このオプションは、シェル環境と各COMMAND EXECUTION ENVIRONMENTサブシェル環境に個別に適用され(上記を参照)、サブシェル内のすべてのコマンドを実行する前にサブシェルを終了させる場合があります。

さらに、:Bashの効果のないコマンドです。

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