shell Bash中没有布尔变量 flag=0,flag=1
反转布尔变量
26
我想尝试简单的脚本
flag=false
while !$flag
do
   read x
   if [ "$x" -eq "true" ]
   then
     flag=true
   fi
   echo "${x} : ${flag}"
done但是,当我运行它时,如果键入true,我会看到x="true"和flag="true",但是循环并没有结束。脚本有什么问题?如何正确地将布尔变量取反?
bash scripting
 —  繁殖  
 source
                  
                
1
见stackoverflow.com/questions/8108249/...
— 阿拉木图
                    
                  
谢谢!我现在
— 知道
                    
                  
Answers:
21
您的脚本中有两个错误。首先,您需要在!和之间留一个空格$flag,否则shell将寻找一个名为的命令!$flag。第二个错误是-eq用于整数比较,但是您正在字符串上使用它。根据您的外壳,您可能会看到错误消息,并且由于条件[ "$x" -eq "true" ]不能为真,循环将永远继续,或者如果您输入任何字符串(包括false),则每个非整数值都将被视为0,并且循环将退出不同于0的数字。
虽然! $flag正确,但是将字符串视为命令是一个坏主意。可以,但是对脚本中的更改非常敏感,因为您需要确保该值$flag只能是trueor false。最好在这里使用字符串比较,例如下面的测试。
flag=false
while [ "$flag" != "true" ]
do
   read x
   if [ "$x" = "true" ]
   then
     flag=true
   fi
   echo "${x} : ${flag}"
done表达所追求的逻辑可能是更好的方法。例如,您可以进行无限循环并在检测到终止条件时将其中断。
while true; do
  read -r x
  if [ "$x" = "true" ]; then break; fi
  echo "$x: false"
done
 — 吉尔斯“别再邪恶了” 
 source
                      
                    
                      使用[内置的ksh,[ x -eq y ]如果x算术表达式解析为与y算术表达式相同的数字,则返回true ,例如,x=2 true=1+1 ksh -c '[ x -eq true ] && echo yes'将输出yes。
                    
— 斯特凡·查泽拉斯
                        
                      
10
虽然Bash中没有布尔变量,但使用算术评估对其进行仿真非常容易。
flag= # False
flag=0 # False
flag=1 # True (actually any integer number != 0 will do, but see remark below about toggling)
flag="some string" # Maybe False (make sure that the string isn't interpreted as a number)
if ((flag)) # Test for True
then
  : # do something
fi
if ! ((flag)) # Test for False
then
  : # do something
fi
flag=$((1-flag)) # Toggle flag (only works when flag is either empty or unset, 0, 1, or a string which doesn't represent a number)这也适用于ksh。如果它在所有POSIX兼容的shell中都可以使用,但我没有感到惊讶,但是还没有检查标准。
 — 确认 
 source
                      
                    
1
                      是否! ! ((val))可以像使用C或C ++一样在Bash中工作?例如,如果val为0 ,则在之后仍为0 ! !。如果val为1,则之后为1 ! !。如果val为8,则在之后将其拉低至1 ! !。还是我需要问另一个问题?
                    
1
-1 | 在POSIX sh中,未定义独立((..));请删除对它的引用
— LinuxSecurityFreak
                        
                      
Vlastimil的问题具体是关于bash的-不是posix shell。当问题与该主题无关时,为什么要投反对票?
— 尼克·布尔
                        
                      
6
如果您完全可以确定该变量将包含0或1,则可以使用按位XOR等于运算符在两个值之间切换:
$ foo=0
$ echo $foo
0
$ ((foo ^= 1))
$ echo $foo
1
$ ((foo ^= 1))
$echo $foo
0
 — 用户971217 
 source
                      
                    
2
这对我有用:
flag=false
while [[ "$flag" == "false" ]]
do
   read x
   if [[ "$x" == "true" ]]
   then
     flag=true
   fi
   echo "${x} : ${flag}"
done但是,实际上,您应该执行以下操作while:
while ! $flag
 — ДМИТРИЙМАЛИКОВ 
 source
                      
                    
0
Shell中没有布尔变量的概念。
shell变量只能是text(一个字符串),并且,在某些情况下,该文本可以被解释为一个整数(1,0xa,010等)。
因此,a flag=true根本不暗示外壳的真实性或错误性。
串
可以执行的操作是字符串比较[ "$flag" == "true" ]或在某些命令中使用变量内容并检查其结果,例如执行true(因为同时存在true一个被调用的可执行文件和一个被调用的可执行文件false)作为命令,并检查该命令的退出代码是否为零(成功)。
$flag; if [ "$?" -eq 0 ]; then ... fi或更短:
if "$flag"; then ... fi如果将变量的内容用作!命令,则如果两个(! cmd)之间存在空格,则可以使用a 取反命令的退出状态,如下所示:
if ! "$flag"; then ... fi该脚本应更改为:
flag=false
while ! "$flag" 
do
   read x
   if [ "$x" == "true" ]
   then
     flag=true
   fi
   echo "${x} : ${flag}"
done整数
使用数值和算术扩展。
在这种情况下,$((0))is 1的退出代码和$((1))is 的退出代码0。
在bash,ksh和zsh中,该算术可以在a内执行((..))(请注意,$缺少开始部分)。
flag=0; if ((flag)); then ... fi
此代码的可移植版本更加复杂:
flag=0; if [ "$((flag))" -eq 0 ]; then ... fi      # test for a number
flag=0; if [ "$((flag))"  == 0 ]; then ... fi      # test for the string "0"在bash / ksh / zsh中,您可以执行以下操作:
flag=0    
while ((!flag)) 
do
   read x
   [ "$x" == "true" ] && flag=1
   echo "${x} : ${flag}"
done或者
您可以将“反转布尔变量”(假设它包含数字值)为:
((flag=!flag))
这将改变的值flag要么0或1。
注意:在将代码作为问题发布之前,请检查https://www.shellcheck.net/中的错误,这足以发现问题。
 — 以撒 
 source
                      
                    
0
until的缩写while !(与Bourne until相反!),因此您可以执行以下操作:
flag=false
until "$flag"
do
   IFS= read -r x
   if [ "$x" = true ]
   then
     flag=true
   fi
   printf '%s\n' "$x : $flag"
done哪个应该和:
flag=false
while ! "$flag"
do
   IFS= read -r x
   if [ "$x" = true ]
   then
     flag=true
   fi
   printf '%s\n' "$x : $flag"
done您也可以将其编写为:
until
   IFS= read -r x
   printf '%s\n' "$x"
   [ "$x" = true ]
do
   continue
doneuntil/ while和之间的部分do不必是单个命令。
!是POSIX Shell语法中的关键字。它需要定界,令牌与后面的令牌分开,并且是管道之前的第一个令牌(! foo | bar否定管道,foo | ! bar尽管某些外壳程序接受它为扩展名,但它还是无效的)。
!true被解释为!true不太可能存在的命令。! true应该管用。!(true)应该在符合POSIX的炮弹工作作为!作为它的后面是分隔的(道理,但在实践中它并不在工作ksh/ bash -O extglob在那里与冲突!(pattern)扩展水珠运营商也不zsh的在那里它与冲突(除SH仿真)glob(qualifiers)与bareglobqual和glob(group)没有。
 — 斯特凡·查泽拉斯 
 source
                      
                    
-1
[ ${FOO:-0} == 0 ] && FOO=1 || FOO=0甚至:
[ ${FOO:-false} == false ] && FOO=true || FOO=false应该做的工作
https://qastack.cn/unix/24500/invert-boolean-variable#:~:text=Shell%E4%B8%AD%E6%B2%A1%E6%9C%89%E5%B8%83%E5%B0%94%E5%8F%98%E9%87%8F%E7%9A%84%E6%A6%82%E5%BF%B5%E3%80%82%20shell%E5%8F%98%E9%87%8F%E5%8F%AA%E8%83%BD%E6%98%AF%20text%20%EF%BC%88%E4%B8%80%E4%B8%AA%E5%AD%97%E7%AC%A6%E4%B8%B2%EF%BC%89%EF%BC%8C%E5%B9%B6%E4%B8%94%EF%BC%8C%E5%9C%A8%E6%9F%90%E4%BA%9B%E6%83%85%E5%86%B5%E4%B8%8B%EF%BC%8C%E8%AF%A5%E6%96%87%E6%9C%AC%E5%8F%AF%E4%BB%A5%E8%A2%AB%E8%A7%A3%E9%87%8A%E4%B8%BA%E4%B8%80%E4%B8%AA%E6%95%B4%E6%95%B0%EF%BC%88%201,%EF%BC%8C%200xa%20%EF%BC%8C%20010%20%E7%AD%89%EF%BC%89%E3%80%82
    
    










