Bash:以grep命令的相反状态退出一行?

时间:2013-03-12 17:10:42

标签: regex bash grep exit exit-code

如何减少以下bash脚本?

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

看起来我应该可以用一个命令来完成它,但我这里总共有3个。

我的节目应该:

  • 阅读recess.txt
  • 退出1(或非零)如果它包含“STATUS:”NOT“Perfect”的行
  • 如果不存在这样的行,则退出0(即所有“STATUS:”行都是“完美”)

答案奖授予最严格的剧本。谢谢!

示例文件

该文件的退出状态0

FILE: styles.css 
STATUS: Perfect!

FILE: contour-styles.css
STATUS: Perfect!

此文件的退出状态1 (或非零):

FILE: styles.css 
STATUS: Perfect!

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

Id's should not be styled
       1. #asdf

11 个答案:

答案 0 :(得分:29)

只需negate返回值。

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

答案 1 :(得分:10)

我遇到了这个,需要一个onlyif声明Puppet。因此,Tgr's bash solution不起作用,我不想像Christopher Neylan's answer那样扩展复杂性。

我最终使用了受Henri Schomäcker's answer启发的版本,但显着简化了:

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.

答案 2 :(得分:7)

要使(使用)$ 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 $ 将其围绕在子shell中,请使用<{1}}:

pytest_addoption

答案 3 :(得分:6)

您实际上根本不需要使用exit。从逻辑上讲,无论grep的结果是什么,你的脚本都会退出。由于shell脚本的退出值是最后一个命令的退出代码,因此只需运行grep作为最后一个命令,使用-v选项反转匹配以更正退出值。因此,您的脚本可以简化为:

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

修改

抱歉,当文件中有其他类型的行时,上述操作无效。为了避免运行多个命令,awk可以用以下内容完成整个shebang:

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

如果您决定使用grep提供的输出,您可以执行以下操作:

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

答案 4 :(得分:5)

如果有人到这里寻找bash返回代码操作:

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

当grep找不到任何内容时,这将返回0(成功),并返回123(失败)。括号是以防任何人在shell提示符下测试它。使用括号,它不会在退出时注销,而只是使用相同的错误代码退出子shell。

我用它来快速检查js文件:

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

答案 5 :(得分:4)

只是否定返回值在set -e上下文中不起作用。但你可以这样做:

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

答案 6 :(得分:1)

使用special ? variable

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

(但请注意,grep也可能会返回2,所以在这种情况下您不希望发生什么。)

答案 7 :(得分: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

答案 8 :(得分:0)

[ $(grep -c -P "STATUS: (?!Perfect)" recess.txt) -eq 0 ]

答案 9 :(得分:0)

我还需要这样一个解决方案,只在语句中编写puppet并提出以下命令:

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

答案 10 :(得分:0)

由于有人已经发布了Puppet解决方案,所以我不妨添加如何反转Ansible运行的shell命令:

  - name: Check logs for errors
    command: grep ERROR /var/log/cassandra/system.log
    register: log_errors
    failed_when: "log_errors.rc == 0"

即您只需将失败条件设置为返回码0。因此,如果我们在日志中 do 找到ERROR一词,此命令将失败。

我选择了此选项而不是grep -v,因为这也会反转grep的输出,因此我们会收到log_errors.stdout_lines中所有不需要的DEBUG / INFO / WARN行。