パターンが見つからない場合、シェルスクリプトが早期に終了するのを防ぐための `set -e` と `grep` 慣用語

パターンが見つからない場合、シェルスクリプトが早期に終了するのを防ぐための `set -e` と `grep` 慣用語

助けが必要です - GNU / LINUX bashのシェルスクリプト環境で:

私はいつも使用しますset -e。常に望むわけではありませんが、終了ステータスがパターンを見つけることができないことを示すときにgrepスクリプトの実行を終了したいと思います。grep1

この問題を解決する方法は次のとおりです。

(私を試してみてください)そのような方法でgrepを呼び出す
と、将来の管理者がアクティブになるまで希望の動作を得ることができます。また、私はアクティブにするのが好きなので、これは私には適していません。set +o pipefailgrep 'p' | wc -lpipefailpipefail

(2回試行)パターンに一致する行のみを
使用するsedか印刷してから、一致する行を使用して一致するパターンをテストします。 toを使用することが私の実際の問題に対する解決策であると思われるので、このオプションは気に入らません。awkwcsedgrep

(試行III)
これは私が一番好きではありません。次のようになります。set +e; grep 'p'; set-e

どんな洞察力/慣用句にも大変感謝いたします。ありがとうございます。

答え1

条件にgrepを入れるifこともでき、終了状態に興味がなければ|| true

例:grepシェルの終了

$ bash
$ set -e
$ echo $$
33913
$ grep foo /etc/motd
$ echo $$
9233

解決策1:0以外の終了ステータスを削除する

$ bash
$ set -e
$ echo $$
34074
$ grep foo /etc/motd || true
$ echo $$
34074

解決策2:終了ステータスを明示的にテストする

$ if ! grep foo /etc/motd; then echo not found; fi
not found
$ echo $$
34074

Bashのマニュアルページディスカッションからset -e

失敗したコマンドが直ちにコマンドリストの一部である場合、シェルは終了しません。しかし、または~まで キーワード、テストの一部もしまたは一生予約語、実行されたコマンドの一部 &&またはリストされた最後のコマンドの後のコマンドは除外&&または、最後のコマンドを除くパイプライン内のすべてのコマンドまたは戻り値が次のようなコマンド

答え2

コマンドが失敗した場合に効果を無効にするには、他の人が言ったように、コマンドerrexitを条件文の一部としてif/elifおよび間に使用するthenか、論理演算子の後に使用するだけで十分です。whileuntildo&&||

errexit終了状態を変更せずに効果を無効にする標準イディオムは次のとおりです。

cmd && true

それはまだ戻ってきます。cmd失敗したがシェルを終了しない場合。

しかし、しばしばあなたが望むのは失敗とそのerrexit影響を無視することです。

したがって、より正式なアプローチは次のとおりです。

cmd || true

これは返されますトゥルーイ成功かどうかcmd

grep返品トゥルーイ入力の1つ以上の行が一致し、エラーが発生しなかった場合それ以外の場合。

通常、次の目的で使用されます。

if grep -q pattern file; then
  echo at least one line of file matched the pattern
  do-something
fi

必要なものがあれば出力で、grep一致がなくても構わない場合は、grep終了ステータスを無視できます。

grep pattern file || true

しかし、あなたは捕まえられないでしょう。間違いたとえば、fileオープンできない、正規表現に構文エラーがある場合、またはgrepその出力を書き込めない場合などです。

grep1不一致とエラーの場合は終了ステータスが使用され、見つからない場合は127に設定され、終了した場合は128より大きい数値に2設定できます。したがって、値に基づいてミスマッチとエラーを明確に区別し、以下を使用してエラーのみをトリガーできる必要があります。$?grep$?errexit

grep pattern file || [ "$?" -eq 1 ]

これは返されますトゥルーイ成功またはgrep一致するものがない場合、失敗すると終了しますerrexit[不一致以外のエラー)$?1

set -o errexitただし、通常、非常に不安定なエラー(別名)に頼るのではなく、適切なエラー処理を実行することをお勧めしますset -e。さまざまな障害モードを区別する必要がある場合は、grep次のことができます。

die() { [ "$#" -eq 0 ] || printf>&2 '%s\n' "$@"; exit 1; }
grep pattern file
case $? in
  (0) echo OK, match;;
  (1) echo OK, no match;;
  (*) handle-error; die;;
esac

答え3

pipefailまた、サブシェルを使用して設定を一時的に無効または無効にすることもできます。

( set +o pipefail ; grep 'p' ) | wc -l

または

( grep 'p' || true ) | wc -l

また、2番目のケースでは括弧が必要なので、より|しっかりとバインドされます。||

答え4

終了ステータスに興味がある別のオプションは次のとおりです。

    FOUND=$(grep whatever here) || true     
    if [ -z $FOUND ]; then
      echo "not found"
    else
      echo "found"
    fi

関連情報