【问题标题】:How to make "if not true condition"?如何制作“如果不是真的条件”?
【发布时间】:2012-05-20 03:07:14
【问题描述】:

我希望在cat /etc/passwd | grep "sysa" 不正确时执行echo 命令。

我做错了什么?

if ! [ $(cat /etc/passwd | grep "sysa") ]; then
        echo "ERROR - The user sysa could not be looked up"
        exit 2
fi

【问题讨论】:

  • ! 不应该在括号内吗?即[ ! EXPR ]
  • @acraig5075 无论哪种方式都有效,但在此语句中根本不需要测试命令(括号内的内容)。

标签: bash if-statement syntax boolean-expression


【解决方案1】:

试试

if ! grep -q sysa /etc/passwd ; then

grep 如果找到搜索目标则返回true,如果没有找到则返回false

所以不是false == true

if shell 中的评估被设计为非常灵活,并且很多时候不需要命令链(如您所写)。

此外,按原样查看您的代码,您使用 $( ... ) 形式的 cmd 替换是值得称赞的,但请考虑该过程的结果。试试echo $(cat /etc/passwd | grep "sysa") 看看我的意思。您可以通过使用 -c (count) 选项来更进一步地进行 grep,然后执行 if ! [ $(grep -c "sysa" /etc/passwd) -eq 0 ] ; then,这有效,但相当老派。

但是,您可以使用最新的 shell 功能(算术评估),例如

if ! (( $(grep -c "sysa" /etc/passwd) == 0 )) ; then ...`

这也让您受益于使用基于 c-lang 的比较运算符 ==,<,>,>=,<=,% 以及其他一些运算符。

在这种情况下,根据 Orwellophile 的评论,算术评估可以进一步缩减,例如

if ! (( $(grep -c "sysa" /etc/passwd) )) ; then ....

if (( ! $(grep -c "sysa" /etc/passwd) )) ; then ....

最后,还有一个名为Useless Use of Cat (UUOC)奖项。 :-) 有些人会跳上跳下哭哥特卡!我只想说grep 可以在它的命令行上取一个文件名,那么为什么在你不需要的时候调用额外的进程和管道构造呢? ;-)

我希望这会有所帮助。

【讨论】:

  • 这真的很傻,从我对一个更难的(问题)的回答[stackoverflow.com/a/30400327/912236]grep "^$user:" /etc/passwd 顺便搜索 /etc/passwd 更正确 - grep -v where 的混乱,i>-v 会反转搜索
  • 是的,解决问题最有效,然后是回答具体问题。我试图回答具体问题。谢谢你的想法。祝大家好运。
  • 不挑你的答案,很喜欢他们。我只是通过我会对用户名进行适当的有界检查,否则如果 OP 确实搜索“sys”或类似的东西,他会感到非常惊讶。再买一辆? (( $( cat file | grep regex | wc -l ) ? 0 : 1 ))
  • 太棒了!由于某种原因,“!grep -qs ...”无法与 /proc/mounts 一起使用,并试图找出是否在 Raspbian 4.9 内核上安装了定期丢弃的 USB 磁盘。这个完美地完成了这项工作!
【解决方案2】:

我认为可以简化为:

grep sysa /etc/passwd || {
    echo "ERROR - The user sysa could not be looked up"
    exit 2
}

或在单个命令行中

$ grep sysa /etc/passwd || { echo "ERROR - The user sysa could not be looked up"; exit 2; }

【讨论】:

  • 很好,但我更喜欢 shellter 先生的回答,因为它是“自我记录的”,更“可读”程序员的意图。
  • 我喜欢这个版本。在echo 末尾添加1>&2 以在stderr 上打印怎么样?
  • @0zkrPM 但是 shellter 版本在 Bourne shell 中不起作用。你会得到!: not found
  • 像这样使用'grep 时避免输出重定向。 -q 抑制输出。
【解决方案3】:

这个

if [[ !  $(cat /etc/passwd | grep "sysa") ]]
Then echo " something"
exit 2
fi

【讨论】:

  • 欢迎来到 Stack Overflow。在 Stack Overflow 上不鼓励仅使用代码的答案,因为它们没有解释它是如何解决问题的。请编辑您的答案以解释此代码的作用以及它如何改进此问题已有的其他投票答案,以便对其他有类似问题的用户有用。
【解决方案4】:

我做错了什么?

$(...) 持有,而不是退出状态,这就是这种方法错误的原因。但是,在这种特定情况下,它确实有效,因为 sysa 将被打印出来,这使得测试语句成真。但是,if ! [ $(true) ]; then echo false; fi 将始终打印 false,因为 true 命令不会向标准输出写入任何内容(即使退出代码为 0)。这就是为什么它需要改写为if ! grep ...; then

另一种选择是cat /etc/passwd | grep "sysa" || echo error。编辑:正如亚历克斯指出的那样,cat is useless here:grep "sysa" /etc/passwd || echo error

发现其他答案相当混乱,希望这对某人有所帮助。

【讨论】:

    【解决方案5】:

    下面是一个示例的答案:

    为了确保数据记录器在线,cron 脚本每 15 分钟运行一次,如下所示:

    #!/bin/bash
    #
    if ! ping -c 1 SOLAR &>/dev/null
    then
      echo "SUBJECT:  SOLAR is not responding to ping" | ssmtp abc@def.com
      echo "SOLAR is not responding to ping" | ssmtp 4151112222@txt.att.com
    else
      echo "SOLAR is up"
    fi
    #
    if ! ping -c 1 OUTSIDE &>/dev/null
    then
      echo "SUBJECT:  OUTSIDE is not responding to ping" | ssmtp abc@def.com
      echo "OUTSIDE is not responding to ping" | ssmtp 4151112222@txt.att.com
    else
      echo "OUTSIDE is up"
    fi
    #
    

    ...对于您可以在蒙太奇中看到的每个数据记录器,依此类推 在http://www.SDsolarBlog.com/montage


    仅供参考,使用&>/dev/null 将命令的所有输出(包括错误)重定向到/dev/null

    (条件只需要ping命令的exit status

    另外,请注意,由于cron 作业以root 运行,因此无需在cron 脚本中使用sudo ping

    【讨论】:

      【解决方案6】:

      在支持它的 Unix 系统上(似乎不是 macOS):

      if getent passwd "$username" >/dev/null; then
          printf 'User %s exists\n' "$username"
      else
          printf 'User %s does not exist\n' "$username"
      fi 
      

      这样做的好处是它可以查询任何可能正在使用的目录服务(YP/NIS 或 LDAP 等)和本地密码数据库文件。


      grep -q "$username" /etc/passwd 的问题在于,当没有这样的用户时,它会给出误报,但其他东西与该模式匹配。如果文件中的其他位置存在部分匹配或完全匹配,则可能会发生这种情况。

      例如,在我的passwd 文件中,有一行说

      build:*:21:21:base and xenocara build:/var/empty:/bin/ksh
      

      这会引发caraenoc 等内容的有效匹配,即使我的系统上没有这样的用户。

      要使grep 解决方案正确,您需要正确解析/etc/passwd 文件:

      if cut -d ':' -f 1 /etc/passwd | grep -qxF "$username"; then
          # found
      else
          # not found
      fi
      

      ...或针对:-delimited 字段中的第一个字段的任何其他类似测试。

      【讨论】:

      • @SDsolar 在这种情况下,bash 可能不会执行您的代码。
      猜你喜欢
      • 2015-08-19
      • 2019-01-24
      • 1970-01-01
      • 2016-11-22
      • 2018-02-24
      • 1970-01-01
      • 2013-06-04
      • 1970-01-01
      • 2013-02-11
      相关资源
      最近更新 更多