在bash中使用所有bash运算符(+,-,/,*,**,&,&&,<<等)和算术扩展
到目前为止,有346k名访问者来到这个问题,我敢打赌其中344.9k人只是想要这个问题的标题的答案:
如何在bash中使用取模运算符?
即使我谷歌搜索"bash modulus"寻找那个答案,最后还是来到了这里。所以,既然我已经弄清楚了,我们就直接跳到正题:
如何在bash中使用取模(%)运算符
只需像这样做:
$((7 % 4))
echo $((7 % 4))
echo "$((7 % 4))"
带变量的示例:
num1="7"
num2="4"
echo $((num1 % num2))
echo $(($num1 % $num2))
echo "$(("$num1" % "$num2"))"
将结果存储到一个变量中:
mod=$((num1 % num2))
echo "$mod"
这些概念的主要学习链接是来自
GNU bash官方用户手册:
- Bash算术扩展
- Bash Shell算术
更多关于bash的"算术扩展"
我从@Mark Longair的回答中学到了上述内容(尽管我花了一些功夫才理解全部内容),那就是我得到下面链接的地方。然后我进行了更多的研究。
$(( ))
部分被称为 "算术扩展",并在官方GNU bash
用户手册中进行了描述,链接在这里:https://www.gnu.org/savannah-checkouts/gnu/bash/manual/bash.html#Arithmetic-Expansion。
基本示例(在每个示例前面加上echo
以查看结果打印到屏幕上):
$((mathematical_expression))
$((7 + 4))
$((7 - 4))
$((7 % 4))
$((7 && 4))
$((7 & 4))
在算术扩展周围不需要双引号。根据上述手册(强调添加):
表达式被视为在双引号内,但括号内的双引号不会被特殊处理。表达式中的所有标记都会经历参数和变量扩展、命令替换和引号去除。结果被视为要评估的算术表达式。算术扩展可以嵌套。
有关所有 shell 算术运算符,请参阅 GNU bash 手册中的"Shell Arithmetic"部分,链接在这里:https://www.gnu.org/savannah-checkouts/gnu/bash/manual/bash.html#Shell-Arithmetic
您基本上可以使用 C 语言的所有数学运算符。算术运算是“在没有溢出检查的固定宽度整数中进行的”,因此如果您执行 echo $((11/10))
或 echo $((19/10))
,两种情况下都会得到 1
,因为对于整数来说,小数部分被截断。
根据刚才提供的手册链接(强调添加):
评估使用固定宽度整数进行,没有检查溢出,但除以0会被捕获并标记为错误。操作符及其优先级、结合性和值与C语言相同。
由于bash中的算术运算符与C语言具有相同的优先级,如上所述,您还可以参考cppreference社区维基上的C运算符优先级:
https://en.cppreference.com/w/c/language/operator_precedence <-- 把它放进你的工具包里。
Shell算术:这里是
GNU Bash手册中支持的所有操作符。
它们按照从高到低的优先级列出。
id++ id--
- 变量后增和后减
++id --id
- 变量前增和前减
- +
- 一元减和加
! ~
- 逻辑和按位取反
**
- 乘方
* / %
- 乘法、除法、取余
+ -
- 加法、减法
<< >>
- 左移和右移
<= >= < >
- 比较
== !=
- 相等和不相等
&
- 按位与
^
- 按位异或
|
- 按位或
&&
- 逻辑与
||
- 逻辑或
expr ? expr : expr
- 条件运算符
= *= /= %= += -= <<= >>= &= ^= |=
- 赋值
expr1 , expr2
- 逗号
在算术中使用不同的进制,例如二进制(基数为2)、八进制(基数为8)和十六进制(基数为16)
要了解如何使用不同的进制(如二进制(基数为2)、八进制(基数为8)或十六进制(基数为16))与bash算术运算符一起使用,请阅读下面几段文字手册中上面的“Shell Arithmetic”列表。
以下是一些快速示例,其中包含用于数学计算的十进制(基数为10)、八进制(基数为8)、十六进制(基数为16)和二进制(基数为2)的输入数字:
echo $((0xa + 5))
echo $((16#a + 5))
echo $((071 + 0xaa))
echo $((8#71 + 16#aa))
echo $((2#1011 + 2))
echo $((2#1111 + 2#11111))
要以十六进制打印,请使用printf "0x%X\n" 数字
:
printf "0x%X\n" $((2#1111 + 2#11111))
要以二进制形式打印,请使用
bc
(参见
这里的我的答案):
printf "0b%s\n" "$(echo "obase=2; $((2#1111 + 2#11111))" | bc)"
另请参阅
- [我的回答] 如何在bash中使用浮点运算?
- 如果你需要一个完整的bash浮点库,可以轻松导入(源代码),请使用我在这里的代码:bash/floating_point_math.sh 在我的eRCaGuy_hello_world存储库中。
- 还可以参考我关于在Bash中使用库的回答:详细示例:如何编写、导入、使用和测试Bash库?
bash
中进行数学运算,请注意,使用负数的取模运算仅返回余数,而不是数学上的取模结果。这意味着,虽然在数学上-12 mod 10
是8
,但在bash
中会计算为-2
。你可以用简单的echo $((-12 % 10))
(-2
)来测试它,并将其与python3 -c "print(-12 % 10)"
(8
)进行比较。 - Lirt$(())
会自动展开变量,所以你不需要在i
前加$
。这样$((i % 5))
就能完美地工作了。 - Yokai