【问题标题】:tail | grep -q always returning true尾巴 | grep -q 总是返回真
【发布时间】:2016-03-13 04:31:44
【问题描述】:

当我执行这段代码时,循环总是在第一次结束(即使auth.log 的最后两行不包含“exit”),这意味着$c 总是得到一些字符串:

while true;
do
    c=$(tail -2 /var/log/auth.log | grep -q "exit")
    if $c ;
    then
            echo "true"
            unset c
            break
    fi

完成

你知道为什么c=$(tail -2 /var/log/auth.log | grep -q "exit") 总是得到某种字符串吗?我认为这是因为tail

我可以使用-o 选项然后比较字符串,但我更喜欢在if 条件内使用布尔值。

【问题讨论】:

  • 我的意思是 grep -q 的输出可以只是“真”(0)(如果有一些字符串匹配“退出”)或(假)(1)如果它是空的,但似乎如果 auth.log 在最后 2 行中没有“exit”,则 $c 有一些字符串
  • 试试这个就明白了:unset c; if $c; then echo "Evaluated to true"; fi
  • 如果我尝试这个,它会跳转到循环
  • 关键是如果你使用一个未设置的参数作为条件,它总是评估为真。查看参数是否等于空字符串的测试将是[ -z "$c" ](或[ -n "$c" ] 以测试它是否不是空字符串),但主要问题已在 mklement0 的答案中得到解答。
  • 谢谢家伙,现在它就像一个魅力

标签: shell


【解决方案1】:

grep -q 在设计上不返回任何输出,它只是通过其退出代码指示是否找到匹配项。

因此,您可以简单地将管道直接用作条件:

while true;
do
    if tail -2 /var/log/auth.log | grep -q "exit";
    then
            echo "true"
            break
    fi
done

至于你尝试了什么:

正如Benjamin W. 在对该问题的评论中所暗示的那样,执行扩展为空字符串命令 始终被视为成功 命令.

注意:由于所讨论的变量是 unset 或在本例中显式分配了一个空(空)字符串,因此命令是否有效地为空并不重要。

因此,鉴于 $c 始终为空 - 因为 grep -q 按照设计从不返回标准输出输出 - if 条件始终评估为真。

要明确:$c,因为它条件中使用(if $c; ...而不是if [ "$c" ]; ...),被解释为执行命令,而不是作为一个字符串来测试是否为空

如果$c 中捕获其输出的命令要生成标准输出输出,您必须使用 条件 进行测试:if [ -n "$c" ]; then ... (或者,更简洁地说,if [ "$c" ]; then ...)。

【讨论】:

  • 所以在我的旧代码中,我正在评估空变量 $c ,当我使用 grep -q 时没有输出,然后变量 c 采用他的默认值 "" 是什么,所以如果我尝试评估它总是正确的。并且 if 必须评估命令而不是变量(输出)
  • @hakimoto:是的,变量作为命令执行如果为空,则始终指示为真。我猜逻辑是:如果没有命令,那么它不会失败,因此退出代码不会设置为非零值。请注意,条件(以及因此 if 语句)仅基于 退出代码 操作,而与任何 stdout(或 stderr)输出无关。同样,如果您在条件内[ "$c" ])评估$c,那么逻辑将反转,因为该值被测试为空:一个空值然后表示假.
猜你喜欢
  • 2017-05-30
  • 2014-04-17
  • 1970-01-01
  • 1970-01-01
  • 2015-05-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多