【问题标题】:expr and if in bashexpr 和 if 在 bash
【发布时间】:2019-02-07 04:40:39
【问题描述】:

这段代码有什么问题?如果我输入数字 25,它会输出 failed 而不是 lol。我错过了什么吗?

read -p "Enter number : " num
if [ `expr $num > 5` ] 
then 
echo "lol" 
else 
echo "failed" 
fi

【问题讨论】:

标签: bash comparison arithmetic-expressions


【解决方案1】:

代码

if [ `expr $num > 5` ] 

其实并不想让你想。它将运行 expr $num > 5,因此评估参数并将输出重定向到名为 5 的文件(“将 25 放入名为 5 的文件中”),if 将评估前一个表达式的返回码。

如果代码是为了检查一个数字是否大于 5,请替换

if [ `expr $num > 5` ] 

[ "$num" -gt 5 ]

-gt 代表greater than

【讨论】:

  • if 不计算前一个表达式的返回码。在这里失败的原因是expr 输出被重定向到文件名5,因此expr 不会向标准输出输出任何内容。如果呼叫是expr $num + 5,代码将回显"lol"
  • 你少了一个空格:[ "$num" -gt 5 ].
  • 只有$num是参数; expr 25 的输出将被写入名为 5 的文件中。
【解决方案2】:

@babtistemm 的回答为您提供了建议的解决方案,但如果您出于某种原因坚持使用(有点陈旧)expr

read -p "Enter number : " num
if expr "$num" '>' 5 >/dev/null
    then 
        echo "lol" 
    else 
        echo "failed" 
fi

注意事项:

  1. 您需要引用>,以便shell 不会将其解释为重定向stdout。你也可以使用\>

  2. $num 中添加双引号也是一种很好的做法,这样expr 会将其解释为one 表达式,从而限制出现非常严重的错误或恶意用户入侵您的程序。 (最好在使用 $num 之前对其进行完整性检查,例如检查它是否为整数。)

  3. 此解决方案需要调用一个新进程expr,这比仅使用test shell 命令花费更多的操作系统资源。

  4. 1234563但与此无关,expr 根据表达式的结果设置其退出状态$?,然后由if 进行测试。 (附注:如果您在调用expr 后尝试echo $?,可能会首先感到惊讶的是$? = 0 表示退出状态为真/成功,而$? != 0 按惯例表示假。)

【讨论】:

  • 对您的输入进行健全性检查也是一个好主意,这样用户提供的数据就不会生成语法上无效的代码(这可能容易受到攻击)。例如:if expr "${num}" : '[0-9][0-9]*$' && expr "$num" '>' 5 >/dev/null; then
  • 当然,上面的代码是 100% 易受攻击的。我担心即使您将第一个操作数引用为"$num",恶意用户也可以在脚本权限下执行任何代码。
  • @ghoti 你说得对,但我认为正则表达式对于 OP 的问题来说太过分了。
【解决方案3】:

你可以在 bash 中使用算术表达式:

if (( num > 5 )); then ...

手册见https://www.gnu.org/software/bash/manual/bash.html#Conditional-Constructs

【讨论】:

    【解决方案4】:

    短线相同:

    read -p 'Enter a number: ' num
    (( num > 5 )) && echo lol || echo fail
    

    可以压缩:

    read -p 'Enter a number: ' num;((num>5))&&echo lol||echo fail
    

    如果第一个命令成功,此语法将起作用!

    read -p 'Enter a number: ' num
    ((num > 5)) && {
          echo lol
          /bin/wrongcommand
          :
     } || echo fail
    

    可以输出:

    lol
    bash: /bin/wrongcommand: No such file or directory
    

    但没有fail 因为:(是true 的别名)总是会成功。

    你当然可以为 fail 分组命令:

    read -p 'Enter a number: ' num
    ((num > 5)) && {
          echo lol
          /bin/wrongcommand
          :
     } || {
          echo fail
          other command
     }
    

    可以写成:

    read -p 'Enter a number: ' num;((num>5))&&{ echo lol;/bin/wrongcommand;:;}||{ echo fail;other command;}
    

    您可以在;} 之间对命令进行分组(注意第一个{ 后面的空格!)

    Enter a number: 4
    fail
    bash: other: command not found
    
    Enter a number: 7
    lol
    bash: /bin/wrongcommand: No such file or directory
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-16
      • 1970-01-01
      • 2011-10-26
      • 1970-01-01
      • 2020-12-18
      相关资源
      最近更新 更多