Ter*_*ior 9 bash arithmetic floating-point
今天早上我的搜索是关于如何在 bash 中比较两个十进制数,我找到了这个答案:如何与 shell 脚本中的浮点数进行比较。然而,这个答案不包括这里的答案:
$ [[ ((3.56 < 2.90)) ]]; echo $?
1
$ [[ ((3.56 < 4.90)) ]]; echo $?
0
Run Code Online (Sandbox Code Playgroud)
考虑到该答案已被否决,并且看起来有些不寻常的 bashism,这种算术评估的准确性是否值得信赖?
Qeo*_*ole 13
bash不懂浮点数。
引用bash手册页,算术评估部分:
评估以固定宽度的整数 […] 完成。
所以((3 < 4))or((3 < 2))实际上是正确的算术表达式。您可以键入以下内容:
$ echo "$((3 < 4)) -- $((3 < 2))"
Run Code Online (Sandbox Code Playgroud)
输出:
1 -- 0
但是$ echo $((3.3 < 3.6))会返回一个语法错误信息。在您的示例中,您实际上是在比较字符串。因此一些例子:
$ [[ ((3.56 < 04.90)) ]]; echo $?
Run Code Online (Sandbox Code Playgroud)
输出:
1
Sté*_*las 13
里面[[...]] <是用于字符串比较。
So [[ 3.56 < 2.90 ]]or [[ (3.56 < 2.90) ]]or [[ ((3.56 < 2.90)) ]]or [[ (((3.56 < 2.90))) ]]... 只是在词法上将3.56字符串与2.90字符串进行比较(并且在词法3上大于10例如)。
对于整数比较,它是[[ 3 -lt 2 ]]or (( 3 < 2 ))。如果要进行浮点比较,则需要ksh93, zshoryash或外部实用程序,例如awkor perl;bash做不到。
例如,您可以定义一个函数,如:
compare() (IFS=" "
exec awk "BEGIN{if (!($*)) exit(1)}"
)
Run Code Online (Sandbox Code Playgroud)
您可以使用例如:
if compare '1.5*10 < 1e3'; then
echo less
fi
Run Code Online (Sandbox Code Playgroud)
或者甚至为此很重要:
if compare '"bar" < "foo"'...
Run Code Online (Sandbox Code Playgroud)
进行字符串比较。
不要将不受控制的外部提供的数据传递给该compare函数,因为它会构成命令注入漏洞(例如,数据被解释为awk代码,awk可以运行命令system())。