bash 的逻辑运算符是如何工作的(或者为什么它们在这里不工作)?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4763460/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do bash's logical operators work (or why don't they work here)?
提问by skyeagle
I have the following wrapper script:
我有以下包装脚本:
#!/bin/bash
$local_time=`date +%H%M`
if [ $local_time -ge 1430 ] && [ $local_time -le 2230 ] ||
[ $local_time -ge 0300 ] && [ $local_time -le 0400 ]
then
echo 'pass'
else
echo 'skip'
fi
The idea being to create a wrapper script that runs a script between two disjoint time intervals. Each of the expressions being OR'd is evaluated correctly, however, when I OR both expressions, the test fails.
这个想法是创建一个包装脚本,在两个不相交的时间间隔之间运行一个脚本。每个被 OR 的表达式都被正确评估,但是,当我对两个表达式进行 OR 时,测试失败。
How do I fix this?
我该如何解决?
回答by SiegeX
You have two problems
你有两个问题
- You don't prefix your variables with a
$when you assign to them, only when you expandthem - You need to enforce operator precedence with parens
( )
$分配给变量时,您不会在变量前加上前缀,只有在扩展它们时- 您需要使用括号强制执行运算符优先级
( )
Also, since you're already using bash, might as well use its better syntax with the (( ))construct that allows you to use the comparison operators < > == !=and you can use $()for command substitution instead of the backticks/gravemarks
此外,由于您已经在使用bash, 不妨将其更好的语法与(( ))允许您使用比较运算符的构造一起使用,< > == !=并且您可以将其$()用于命令替换而不是反引号/墓碑
#!/bin/bash
local_time=$(( 10#$( date +'%H%M' ) ))
if (( ( local_time >= 1430 && local_time <= 2230 ) ||
( local_time >= 10#0300 && local_time <= 10#0400 ) ))
then
echo 'pass'
else
echo 'skip'
fi
Numbers that start with a zero are interpreted as octal.
Also, any number that start with 0 and contains an 8 or 9 will print an error.
Prefixing (10#) solves that.
以零开头的数字被解释为八进制。
此外,任何以 0 开头并包含 8 或 9 的数字都会打印错误。
前缀 (10#) 解决了这个问题。
回答by Ignacio Vazquez-Abrams
bash does not have "logical operators"; those are "conditional chains". Logic belongs in the test.
bash 没有“逻辑运算符”;这些是“条件链”。逻辑属于测试。
if [[ ( 10#${local_time} -ge 10#1430 && 10#${local_time} -le 10#2230 ) || \
( 10#${local_time} -ge 10#0300 && 10#${local_time} -le 10#0400 ) ]]
then
...
回答by Ignacio Vazquez-Abrams
You just need to enforce proper precedence with a couple of parenthesis:
您只需要使用几个括号强制执行适当的优先级:
#!/bin/bash
local_time=$(date +%H%M)
if ( [ "$local_time" -ge 1430 ] && [ "$local_time" -le 2230 ] ) ||
( [ "$local_time" -ge 0300 ] && [ "$local_time" -le 0400 ] )
then
echo 'pass'
else
echo 'skip'
fi
Reason: Inside an AND-OR list &&and ||have equal precedence.
Note: Inside [ ]numbers that start with 0 are not interpreted as octals.
原因:在 AND-OR 列表中&&并且||具有相同的优先级。
注意:内部[ ]以 0 开头的数字不会被解释为八进制。
Other changes:
其他变化:
- The left side of an equal should have just the variable name (No
$). - It is recommended to use
$()instead of``. - Quote variables inside
[ ].
- 等号的左侧应该只有变量名 (No
$)。 - 建议使用
$()代替``。 - 引用里面的变量
[ ]。

