【问题标题】:Could you explain the syntax of math in a bash shell?你能解释一下 bash shell 中的数学语法吗?
【发布时间】:2020-01-15 20:34:50
【问题描述】:
for i in {1..99}
do
  if ([ $((i % 2)) -eq 1 ])
  then
      echo $i
  fi
done

我正在学习 bash,并试图更好地理解第 3 行。为什么 $((i % 2)) 必须用括号括起来,为什么我不能将 $ 符号放在 @ 旁边987654324@点赞:

([ (($i % 2)) -eq 1 ])

([ ($(i % 2)) -eq 1 ])

?

【问题讨论】:

  • 单括号用于在子shell中执行命令。
  • 使用if ([ ... ]) 很奇怪。不需要外括号。
  • 一般来说,shell 语法非常 依赖于上下文。您可以在 $(( ))(以及其他一些“算术”上下文)中使用的语法与您可以在其他地方使用的语法大不相同。
  • 正如 Barmar 所说,单括号用于在子 shell 中执行命令,并且有助于将命令的输出存储在 vars 中,例如 var=$(ls /home) 如果你想做一些数学运算,你应该使用双 $((a+b))或正方形 $[a+b] 你实际上可以把 $ 放在里面,但这里是多余的。 if 之后的测试语句应该放在单方括号或双(更好)方括号中。

标签: bash for-loop math


【解决方案1】:

$((...)) 中的所有内容都被视为算术表达式。您可以在算术表达式中使用参数扩展,但裸字符串被解释为使用其(整数)值的变量。你可以写

if [ $(( i % 2 )) -eq 1 ]

检查i 是否为奇数。您还可以检查表达式中的相等性,因为如果 x == y$(( x == y )) 评估为 1,否则为 0,但您仍然需要将 值与某物进行比较。

bash 中,您可以使用算术命令,如果结果值非零,则退出状态为0,否则为1。这可以让你写

if (( i % 2 == 1 )); then

【讨论】:

  • 所以要直接回答这个问题,你不能使用(($i % 2))($(i % 2)) 来做数学,因为它们都不是$((...)) 的形式。
  • 嗯,你可以使用(( $i % 2 )),但它是一个命令,而不是一个表达式。两者只是在不同的上下文中使用。
  • @thatotherguy 例如,((++i)) 增加 i 工作正常。
  • 不在 OP 使用它的上下文中
  • 你甚至可以写((i%2))||printf '%d is even\n' "$i"
【解决方案2】:

$(( expression )) 是计算算术表达式的语法,并将该语法替换为该表达式的结果。它记录在 Bash 手册 here;

算术表达式的语法在here 中描述。在变量名前加$是可选的,所以你也可以写成$(($i % 2))

你必须把它用两个括号括起来,因为$(...) 已经有一个含义,它用于command substitution$(some command) 执行some command,然后替换为命令的输出。

[ ... ] 周围不需要括号。编写if 语句的正常方式是

if [ $((i % 2)) -eq 1 ]

你也可以写成

if (( i % 2 == 1 ))

(( expression )) 计算算术表达式,然后根据结果是零还是非零设置其退出状态。

【讨论】:

  • 如果你想完全取消if,你也可以写成(( i % 2 == 1 )) && echo $i...
  • 是的,但我非常相信if,所以我自己很少提及。
  • 我写了 makefile,if 很痛苦,但我明白你的意思。
【解决方案3】:

既然你指定bash,最简单的就是

for i in {1..99}
do  if ((i % 2)) 
    then echo $i
    fi
done

((i % 2)) 将返回 i mod 2,它始终为零或一。这个特殊的结构表现得像一个 C 风格的布尔值,所以零是假的,其他的都是真的(与 [[ ... ]] 的行为相反,它使用 return 零代码表示真/好)。

【讨论】:

    【解决方案4】:

    你也可以使用expr:

    for i in {1..99}
    do
      num=`expr i % 2`
      if (( num == 1 ))
      then
          echo $i
      fi
    done
    

    【讨论】:

      猜你喜欢
      • 2016-07-25
      • 1970-01-01
      • 1970-01-01
      • 2023-03-15
      • 2018-03-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多