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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-17 23:19:35  来源:igfitidea点击:

How do bash's logical operators work (or why don't they work here)?

bashboolean

提问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

你有两个问题

  1. You don't prefix your variables with a $when you assign to them, only when you expandthem
  2. You need to enforce operator precedence with parens ( )
  1. $分配给变量时,您不会在变量前加上前缀,只有在扩展它们时
  2. 您需要使用括号强制执行运算符优先级 ( )

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 $)。
  • 建议使用$()代替``
  • 引用里面的变量[ ]