[:shell编程中的意外操作符

kit*_*ang 173 linux bash shell

我的代码:

    #!/bin/sh
    #filename:choose.sh
    read choose
    [ "$choose" == "y" -o "$choose" == "Y" ] && echo "Yes" && exit 0
    [ "$choose" == "n" -o "$choose" == "N" ] && echo "No"  && exit 0
    echo "Wrong Input" && exit 0
Run Code Online (Sandbox Code Playgroud)

但是当我执行时

    sh ./choose.sh
Run Code Online (Sandbox Code Playgroud)

终端提示我

   [: 4: n: :Unexpected operator
   [: 5: n: :Unexpected operator
Run Code Online (Sandbox Code Playgroud)

我的bash脚本有什么错误吗?谢谢!

Wol*_*lph 297

你的bash脚本没有错误.但是你用sh执行它,它的语法不太广泛;)

所以,bash ./choose.sh改为运行:)

  • 是.它们是完全不同的贝壳.虽然,bash是基于并且在很大程度上可以与sh进行向后兼容,但它们实际上可能是您系统上的相同程序,但仍然会根据您使用的名称而有所不同.您可以通过将第一行更改为"#!/ bin/bash"并使文件可执行,并运行`./ choose.sh`来自动使用bash运行脚本. (10认同)
  • 这个答案有些错误.完全正确的是现在Nietzche-jou的最高票.`sh`支持`[`.`==`适用于Bash内置函数`[[`,`test`和`[`while [单个`=`是POSIX版本的`[`和`test`](http:// pubs. opengroup.org/onlinepubs/009695399/utilities/test.html).(Bash手册说同样的,BTW.)因为这需要Bash对可移植性是不必要的伤害.命令名是`[`或`test`,`]`只是非必要的,未使用的最后一个参数.许多shell将这些实现为内置函数,[如维基百科所说](http://en.wikipedia.org/wiki/Test_%28Unix%29). (8认同)
  • 解决我的问题.谢谢!然后命令"sh"和"bash"之间有什么区别吗? (3认同)
  • `bash`语法是`sh`语法的超集 - 系统上的`/ bin/sh`可执行文件可能只提供标准的`sh`功能,其中不包括`[]`-style测试. (3认同)
  • @Wolph通过写错部分,我的意思是两件事.首先,问题不在于Bash vs sh语法,两者都可以正确地调用`[`命令.它是`[`命令参数的语法,这不是sh的业务.其次,Bash对于这样的工作来说太过分了,特别是当存在一个更简单的解决方案时.这并不是真的错,因为它也解决了这个问题,但我认为这通常是不好的建议.这导致初学者得出错误的结论,即Bash解决了他们的问题.它比POSIX所需的功能有许多不可移植的扩展.我相信我们应该引导初学者编写便携式程序. (3认同)

Nie*_*jou 280

POSIX sh不了解==字符串相等性,因为这是一种bash -ism.请=改用.

其他人说sh不支持括号是错误的,顺便说一句.

  • +1这是比使用bash,IMO不必要的更好的答案. (50认同)
  • 是的,我尝试将"=="替换为"=",脚本也可以通过"sh ./choose.sh"执行.Bash和sh支持括号. (5认同)
  • 在我的特定情况下,默认情况下,My Teamcity代理正在运行sh,并且我不想更改该设置(它会产生其他问题)。这里需要SH,我认为这对于必须使用sh的人是正确的答案 (2认同)
  • 仍然是一个非常有价值的提示。很多 docker 镜像都有 sh 而没有 bash。 (2认同)

Jac*_*ott 8

To execute it with Bash, use #!/bin/bash and chmod it to be executable, then use

./choose.sh
Run Code Online (Sandbox Code Playgroud)


Any*_*orn 5

你必须使用bash代替或使用标准sh重写你的脚本

sh -c 'test "$choose" = "y" -o "$choose" = "Y"'
Run Code Online (Sandbox Code Playgroud)

  • @ kit.yang如何更方便?由于人们未能意识到[是测试的同义词以及通过括号周围省略的空格而产生的持续错误而导致的历史混淆,几乎不能补偿所保存的单个字符.("if [$ x = 5]"vs"if test $ x = 5"; 13 chars vs 14). (3认同)

del*_*bel 5

In fact the "[" square opening bracket is just an internal shell alias for the test command.

So you can say:

test -f "/bin/bash" && echo "This system has a bash shell"
Run Code Online (Sandbox Code Playgroud)

or

[ -f "/bin/bash" ] && echo "This system has a bash shell"
Run Code Online (Sandbox Code Playgroud)

... they are equivalent in either sh or bash. Note the requirement to have a closing "]" bracket on the "[" command but other than that "[" is the same as "test". "man test" is a good thing to read.


gho*_*g74 5

你可以使用case/esac而不是if/else

case "$choose" in
  [yY]) echo "Yes" && exit;;
  [nN]) echo "No" && exit;;
  * ) echo "wrong input" && exit;;
esac
Run Code Online (Sandbox Code Playgroud)