web-dev-qa-db-ja.com

バッシュ:grepコマンドの反対のステータスで終了するワンライナー?

次のbashスクリプトを削減するにはどうすればよいですか?

grep -P "STATUS: (?!Perfect)" recess.txt && exit 1
exit 0

たった1つのコマンドでできるはずですが、ここでは合計3つです。

私のプログラムは:

  • Reject.txtを読む
  • 「ステータス:」が「完全」ではない行が含まれている場合は、1(またはゼロ以外)を終了します。
  • そのような行が存在しない場合は0を終了します(つまり、すべての「ステータス:」行は「完全」です)

回答賞は最も厳しいスクリプトに与えられます。ありがとう!

ファイルの例

このファイルのプログラムにはexit statusが必要です:

FILE: styles.css 
STATUS: Perfect!

FILE: contour-styles.css
STATUS: Perfect!

プログラムには、このファイルに対してexit status 1(または0以外)が必要です。

FILE: styles.css 
STATUS: Perfect!

FILE: contour-styles.css
STATUS: Busted 
FAILURES: 1 failure

Id's should not be styled
       1. #asdf
30
Sean Adkinson

ただ negate 戻り値。

! grep -P "STATUS: (?!Perfect)" recess.txt
30
Tgr

私はこれに遭遇し、Puppetにonlyifステートメントが必要でした。そのため、 Tgrのbashソリューション は機能せず、 Christopher Neylanの回答 のように複雑さを拡張したくありませんでした。

私は HenriSchomäckerの答え に触発されたバージョンを使用することになりましたが、特に単純化されました。

grep -P "STATUS: (?!Perfect)" recess.txt; test $? -eq 1

これは非常に単純に終了コードを反転し、テキストが見つからない場合にのみ成功を返します。

  • Grepが0(一致が見つかった)を返す場合、test 0 -eq 1は1を返します。
  • Grepが1を返す場合(一致が見つからない場合)、test 1 -eq 1は0を返します。
  • Grepが2(エラー)を返した場合、test 2 -eq 1は1を返します。

これはまさに私が欲しかったものです。一致が見つからない場合は0を返し、そうでない場合は1を返します。

11
cincodenada

set -eで動作させるには、サブシェルで()で囲みます。

$ cat test.sh 
#!/bin/bash

set -ex
(! ls /tmp/dne)
echo Success
$ ./test.sh 
+ ls /tmp/dne
ls: cannot access /tmp/dne: No such file or directory
+ echo Success
Success
$ mkdir /tmp/dne
$ ./test.sh 
+ ls /tmp/dne
$ 
7
Robpol86

実際には、exitを使用する必要はまったくありません。論理的には、grepの結果に関係なく、スクリプトはとにかく終了します。シェルスクリプトの終了値は最後に実行されたコマンドの終了コードなので、-vオプションを使用してgrep runを最後のコマンドとして実行し、一致を反転させて終了を修正します値。したがって、スクリプトは次のように削減できます。

grep -vqP "STATUS: (?!Perfect)" recess.txt

編集:

ファイルに他のタイプの行がある場合、上記は機能しません。ただし、複数のコマンドを実行しないようにするために、awkは次のような方法でシバン全体を実行できます。

awk '/STATUS: / && ! /Perfect/{exit 1}' recess.txt

Grepが提供するはずの出力が必要であると判断した場合は、次のようにすることができます。

awk '/^STATUS: / && ! /Perfect/{print;ec=1} END{exit ec}' recess.txt
6

誰かがbashの戻りコード操作を探してここに来た場合:

(grep <search> <files> || exit 0 && exit 123;)

これにより、grepで何も見つからなかった場合は0(成功)が返され、見つかった場合は123(失敗)が返されます。括弧は、シェルプロンプトでそのままテストする場合に使用します。括弧を付けると、終了時にログアウトせず、同じエラーコードでサブシェルを終了します。

私はそれをjsファイルの簡単な構文チェックに使用します:

find src/js/ -name \*js -exec node \{\} \; 2>&1 | grep -B 5 SyntaxError || exit 0 && exit 1;
5
gcb

戻り値を否定するだけでは、set -eコンテキストでは機能しません。しかし、あなたはできる:

! grep -P "STATUS: (?!Perfect)" recess.txt || false
4
Eric Woodruff

特別な?変数

grep -P "STATUS: (?!Perfect)" recess.txt
exit $((1-$?))

(ただし、grepも2を返す可能性があるため、このような場合に何を実行するかは明確ではありません。)

1

Grepの回答の問題は、ファイルが空の場合、ファイルが完全であるかのように、クリーンな応答が返されることです。だから私は個人的にこれのためにgrepをあきらめてawkを使いました。

awk 'BEGIN{ef=2}; /STATUS: Perfect/{ ef=0;}; /STATUS: Busted/{ print;eff=3;}; END{exit (ef+eff)}' a.txt ; echo $?

This has exit status:
 0 :  Perfect and !Busted
 2 : !Perfect and  Busted
 3 :  Perfect and  Busted
 5 : !Perfect and !Busted
1
M Hutson
[ $(grep -c -P "STATUS: (?!Perfect)" recess.txt) -eq 0 ]
0
Chris

私はまた、ステートメントをifし、次のコマンドを考え出した場合にのみ人形を書くためのそのような解決策を必要としました:

/bin/grep --quiet 'root: [email protected]' /etc/aliases; if [ $? -eq 0 ]; then test 1 -eq 2; else test 1 -eq 1; fi;

0