我读过很多关于bash中布尔或条件语法的特定用法的答案,但没有一个符合许多人所需的最佳实践(如果你还没有,我建议你先读过这些问题,然后再继续这个问题:搜索bash布尔变量和条件表达式,并阅读前五个(。
困难在于bash没有一个而是有很多不一致、矛盾和反直觉的语法,这在SE中的矛盾答案中得到了很好的反映
目标:知道bash没有布尔类型,只有条件语句、运算符、状态代码和函数,以确定在bash脚本中广泛使用逻辑演算和执行条件控制的最佳语法。广泛意味着可用于条件控制命令、变量和运算符。
IMO应满足所有这些要求的最佳做法,按最重要的顺序排列:
- 简明if,while,对于语句和三元运算符?:
- 布尔值变量的简明赋值与调用
- 简洁的布尔演算运算符or、and、not和带有命令返回状态代码和变量的圆括号
竞争语法示例:
- 语句:
if [[
if [
if command
if $variable
- 作业:
t=true
t=1
t=$(true)
t=''
t=0
- 运算符:
[ true -a false ]
( true && false )
(( true * false ))
那么,最好使用什么语法,例如,对于这个实际示例,但在其他地方也是:
boolresutl1=if commandA or ( $numvarB > $numvarC ) then true
boolresult2=commandD
boolresult3=whatever
if boolresult1 or boolresult2 and not boolresult3 then blabla
最佳答案还将表明,拟议最佳实践的替代方案过于冗长。
编辑:这是一段有效的代码片段,但仍然可以提高清晰度和简洁性。
逻辑的目标是根据文件修改日期的一组时间条件以及每年、每季度、每月、每周和每天的文件保留策略设置变量keepFILE。并删除不符合该条件的文件。我对脚本的关键设计选择是true条件的值,介于NULL(满足if$var但不满足[[$var]](或"true"(满足[[$var]]但不满足if$val(之间。
# date -d @12345 (seconds since epoch) formats: +%u (7= Sunday) +%d (01= 1st dom) +%m (01=Jan)
unset isY isQ isM isW
# is beg of Week ?
[[ "$(date -d @$filedatesecs +%u)" = 7 ]] && isW=true
# is beg of Month ?
[[ "$(date -d @$filedatesecs +%d)" = 01 ]] && isM=true
# is beg of Quarter ?
[[ $isM && $(date -d @$filedatesecs +%m) =~ ^(01|04|07|10)$ ]] && isQ=true
# is beg of Year ?
[[ $isM && "$(date -d @$filedatesecs +%m)" = 01 ]] && isY=true
unset keepD keepW keepM keepQ keepY keepFILE
[[ $fileagedays -le $maxdaysD ]] && keepD=true
[[ $fileagedays -le $maxdaysW ]] && [[ $isW ]] && keepW=true
[[ $fileagedays -le $maxdaysM ]] && [[ $isM ]] && keepM=true
[[ $fileagedays -le $maxdaysQ ]] && [[ $isQ ]] && keepQ=true
[[ $fileagedays -le $maxdaysY ]] && [[ $isY ]] && keepY=true
[[ $keepD || $keepW || $keepM || $keepQ || $keepY ]] && keepFILE=true
您的伪代码
# boolresutl1=if commandA or ( $boolvarB > $boolvarC ) then true
# boolresult2=commandD
# boolresult3=whatever
# if boolresult1 or boolresult2 and not boolresult3 then blabla
最好用之类的东西写
# Assuming `boolVarB` and `$boolvarC` are integer-valued.
if commandA || [ "$boolvarB" -gt "$boolvarC" ] || commandD && ! whatever; then
blabla
fi
注意,||
和&&
具有相等的优先级;CCD_ 15仅在commandA
和[
均失败且commandD
成功的情况下运行。如果需要分组,请使用{ ... ; }
,例如
# Only run commandC if commandA fails and commandB succeeds,
# not when either commandA or commandB succeeds.
if commandA || { commandB && commandC; }; then
如果出于任何原因需要记住退出状态以供以后使用,请立即保存$?
:的结果
commandA || [ "$boolvarB" -gt "$boolvarC" ]
result1=$?
commandD
result2=$?
whatever
result3=$?
...
if [ "$result1" -eq 0 ] || [ "$result2" -eq 0 ] || commandD && [ "$result3" -ne 0 ]; then
blablabla
fi
一些评论:
t=$(true)
与t=
完全等效,只是它需要更长的时间,因为true
不会向标准输出写入任何内容-a
和-o
运算符已过时且不符合标准。永远不要使用它们;用[ x ] && [ y ]
代替[ x -a y ]
和用[ x ] || [ y ]
代替[ x -o y ]
(( true * false ))
(对于适当的整数值变量(只是不必要的混淆