Bash:条件表达式和(伪)布尔变量的最佳实践语法是什么



我读过很多关于bash中布尔或条件语法的特定用法的答案,但没有一个符合许多人所需的最佳实践(如果你还没有,我建议你先读过这些问题,然后再继续这个问题:搜索bash布尔变量和条件表达式,并阅读前五个(。

困难在于bash没有一个而是有很多不一致、矛盾和反直觉的语法,这在SE中的矛盾答案中得到了很好的反映

目标:知道bash没有布尔类型,只有条件语句、运算符、状态代码和函数,以确定在bash脚本中广泛使用逻辑演算和执行条件控制的最佳语法。广泛意味着可用于条件控制命令、变量和运算符。

IMO应满足所有这些要求的最佳做法,按最重要的顺序排列:

  1. 简明if,while,对于语句和三元运算符?:
  2. 布尔值变量的简明赋值与调用
  3. 简洁的布尔演算运算符or、and、not和带有命令返回状态代码和变量的圆括号

竞争语法示例:

  1. 语句:if [[if [if commandif $variable
  2. 作业:t=truet=1t=$(true)t=''t=0
  3. 运算符:[ 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

一些评论:

  1. t=$(true)t=完全等效,只是它需要更长的时间,因为true不会向标准输出写入任何内容
  2. -a-o运算符已过时且不符合标准。永远不要使用它们;用[ x ] && [ y ]代替[ x -a y ]和用[ x ] || [ y ]代替[ x -o y ]
  3. (( true * false ))(对于适当的整数值变量(只是不必要的混淆

最新更新