意外的if语句行为

时间:2015-09-27 16:37:50

标签: bash shell

我正在运行一个小的bash脚本,但即使条件错误,我也无法弄清楚为什么它会进入if块。

$ cat script.sh 
#!/bin/bash

if [[ "$@"="-h" || "$@"="--help" ]]
then
    echo 'Show help'
    exit
fi

echo 'Do stuff'
$ ./script.sh 
Show help
$ bash -x script.sh 
+ [[ -n =-h ]]
+ echo 'Show help'
Show help
+ exit
$ bash -x script.sh -option
+ [[ -n -option=-h ]]
+ echo 'Show help'
Show help
+ exit

当我没有传递任何参数时,为什么$@等于-n?即使它是,-n =-h如何评估为真?当我传递一个参数-option时,为什么它也被评估为真?

3 个答案:

答案 0 :(得分:4)

空白是重要的。 [[的参数之间的空格是强制性的。

if [[ "$@" = "-h" || "$@" = "--help" ]]

此外,"$@"表示"所有命令行参数"。最好只检查一个参数。

if [[ "$1" = "-h" || "$1" = "--help" ]]

对于它的价值,[[中的变量扩展不必引用。它并没有伤害,引用你的变量实际上是一个很好的习惯,但如果你想要你可以删除引号。

if [[ $1 = -h || $1 = --help ]]

答案 1 :(得分:1)

如果string不为空,则

[[ string ]]返回true,即它是

的缩写
[[ -n string ]]

在您的情况下,字符串为=-h,这就是您看到

的原因
[[ -n =-h ]]

要测试字符串相等性,您必须使用=(或==)运算符,该运算符必须以空格开头和后跟。

[[ "$@" = "-h" ]]

请注意"$@"表示所有参数:

set -- a b c
set -x
[[ "$@" == 'a b c' ]] && echo true

给出

+ [[ a b c == \a\ \b\ \c ]]
+ echo true
true

答案 2 :(得分:1)

其他答案已经解释了您的代码存在的问题。这个显示

  • 不需要[[ ... ]]这样的基础知识,
  • 您可以通过使用for循环检查命令行参数中的至少一个是否与-h--help匹配来获得灵活性。

脚本

#!/bin/sh

show_help=0
for arg in "$@"; do
  shift
  case "$arg" in
    "--help")
      show_help=1
      ;;
    "-h")
      show_help=1
      ;;
    *)
      ;;
  esac
done

if [ $show_help -eq 1 ]; then
  printf "Show help\n"
  exit
fi

测试

通过运行

使脚本(称为“foo”)可执行后
chmod u+x foo

我得到以下结果

$ ./foo
$ ./foo -h
Show help
$ ./foo --help
Show help
$ ./foo bar
$ ./foo bar --help
Show help
$ ./foo bar --help baz -h
Show help