【问题标题】:Confused about bash conditionals [duplicate]对bash条件感到困惑[重复]
【发布时间】:2021-11-12 05:15:24
【问题描述】:

我很困惑:

echo "i-am-sure-this-is-here" > /tmp/myfile
if [[ $(grep -q sure /tmp/myfile) ]] ; then echo "Found!" ; else echo "wtf! not found" ; fi

这给出了:

wtf! not found

所以我尝试了一些更简单的方法:

if [[ true ]] ; then echo "true -> expected" ; else echo "true -> unexpected" ; fi
if [[ false ]] ; then echo "false -> unexpected" ; else echo "false -> expected" ; fi

这给了我一些意想不到的东西:

true -> expected
false -> unexpected

我显然不明白这一点。一些问题:

  1. 为什么false 是真的?
  2. 是否有条件评估命令的退出代码?我预计0 退出代码表示truetrue 命令的返回代码),任何非0 退出代码表示falsefalse 命令返回1)李>

如何在bash 中评估if-else-fi 构造中的命令的退出代码,而不必返回到显式地将退出代码($?) 与预期值进行比较,这是丑陋且不可读的?

我知道这会奏效:

grep -q sure /tmp/myfile
if [[ $? -eq 0 ]] ; then echo "Found!" ; else echo "wtf! not found" ; fi

但这更长(2 行而不是 1 行),而且更丑。

【问题讨论】:

  • [[ <something> ]] 如果<something> 不是空字符串,则为真。 grep -q 不打印任何内容,因此 [[ $(grep -q …) ]] 将始终为 false。 [[ false ]] 是真的,因为 false 这个词对 Bash 没有任何“意义”,它不是一个空字符串。要使用grep 作为条件,只需使用if grep -q …; then …
  • 但这更长(2 行而不是 1 行),而且更丑:更长更丑:是的。至于行数,这取决于你。如果您愿意,可以将整个 bash 脚本写成一行。实际上,我也会将 if 语句分散到 6 行以提高可读性,而不是将其压缩成一行,但这是个人喜好问题。
  • 您应该使用基本的test[ 内置插件。

标签: bash if-statement subprocess


【解决方案1】:

if 测试其“参数”的状态码。因此

if grep -q sure /tmp/myfile
then
  echo found
fi

会做的。

【讨论】:

  • 所以if [[ 有作为参数[[?
  • grep 一样,[[ ... ]] 也是一个独立的命令,正如您在执行(例如)[[ abc == *c ]] && echo true 时所看到的那样。 [[ ... ]] 如果条件满足则将退出代码设置为 0,否则设置为 1。
  • @DingDong 请看看bash conditional expressions是如何工作的。
  • 这里有点迂腐,但命令是[[]] 只是该命令的一个参数。
  • @sjsam 我不是对条件表达式感到困惑,而是对 if 如何评估这些表达式的结果感到困惑。
【解决方案2】:

请阅读[[ 复合命令。带有选项 -q 的 Grep 不输出任何内容:

$ grep --help
  ...
  -q, --quiet, --silent     suppress all normal output
  ...

这就是第一次检查失败的原因。 两次尝试的第二个检查都是正确的,因为这就是[[ ]] 的工作方式 true|false 没关系,您可以在此处写下您想要的任何内容,它总是正确的。只有空字符串会失败。

$ [[ yes ]] && echo ok || echo fail
ok

$ [[ no ]] && echo ok || echo fail
ok

$ [[ fail ]] && echo ok || echo fail
ok

$ [[ '' ]] && echo ok || echo fail
fail

但您实际上并不需要使用test[[]]|[] 来检查grep。使用它的退出代码:

grep -q sure /tmp/myfile && echo ok || echo fail
ok

为了防止 Chepner 在 cmets 中所说的,可以使用这种结构:

a && (b; exit 0) || c

【讨论】:

猜你喜欢
  • 2015-02-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-21
  • 2018-08-15
  • 2016-02-21
  • 2023-03-08
  • 1970-01-01
相关资源
最近更新 更多