Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/joomla/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Linux Bash脚本:[test]中的参数太多_Linux_Bash_Testing_Quoting - Fatal编程技术网

Linux Bash脚本:[test]中的参数太多

Linux Bash脚本:[test]中的参数太多,linux,bash,testing,quoting,Linux,Bash,Testing,Quoting,我有下面的bash脚本: #!/bin/bash # [ $# -eq 1 -a $1 = "--help" -o $# -eq 0 ] && { echo Help will come here } 当我运行它时: $ ./script ./script: line 3: [: too many arguments $ ./script --help Help will come here 正如您所看到的,当我不传递参数($#-eq 0)时,它会失败,因为“参数太多”

我有下面的bash脚本:

#!/bin/bash
#
[ $# -eq 1 -a $1 = "--help" -o $# -eq 0 ] && {
  echo Help will come here
}
当我运行它时:

$ ./script 
./script: line 3: [: too many arguments
$ ./script --help
Help will come here
正如您所看到的,当我不传递参数($#-eq 0)时,它会失败,因为“参数太多”。 所以,我直接在终端上测试了它:

$ a=1;b=2;c=3
$ [ $a -eq 1 -a $b -eq 2 -o $c -eq 3 ] && echo ok
ok
$ [ $a -eq 0 -a $b -eq 2 -o $c -eq 3 ] && echo ok
ok
$ [ $a -eq 0 -a $b -eq 0 -o $c -eq 3 ] && echo ok
ok
$ [ $a -eq 0 -a $b -eq 0 -o $c -eq 0 ] && echo ok
$ [ $a -eq 0 -a $b -eq 2 -o $c -eq 0 ] && echo ok
$ [ $a -eq 1 -a $b -eq 2 -o $c -eq 0 ] && echo ok
ok
所以,如果它在终端中工作得很好,为什么它不能传递参数呢


谢谢,

这样表达您的病情:

[ $# -eq 1 ] && [ "$1" = "--help" ] || [ $# -eq 0 ]
实际上,
[
是一个命令,命令中的以下元素会进行分词。如果参数为空(或包含空格且不带引号),您可能会遇到意外。不推荐使用
-a
-o

请注意,如果要在
echo
语句之前使用
&&
逻辑运算符(而不是
if
语句),则需要将上述内容括在大括号内,否则运算符优先级(加上延迟求值)可能会产生不正确的结果

{ [ $# -eq 1 ] && [ "$1" = "--help" ] || [ $# -eq 0 ] ; } && { echo...
如果您不介意使用特定于Bash的语法,还可以编写:

[[ $# -eq 1 && $1 = "--help" || $# -eq 0 ]]
请注意,在这种情况下,不需要双引号
$1
,因为
[[]]
构造是特殊的shell语法,而不是命令,并且里面的内容不受分词的影响。因为只有一个测试,所以在
&&&{echo…
尝试以下操作:-

[$#-eq 1]|[$1=“--help”]|[$#-eq 0]

这样,如果提供了--help或键入了1,它将自动显示


我认为$#是造成问题的原因,因为第一个和第二个条件都有$#

当您在没有参数的情况下执行脚本时,会出现错误,因为您的条件与空白字符匹配,请参见下文-

$sh -x kk.sh 
+ '[' 0 -eq 1 -a = --help -o 0 -eq 0 ']'
kk.sh: line 3: [: too many arguments
正如您所看到的,没有可匹配的值

当您将在终端中执行以下命令时-

$[ $a -eq 1 -a $b -eq 2 -o $c -eq 3 ] && echo ok
-bash: [: too many arguments
$a=1;b=2;c=3
$[ $a -eq 1 -a $b -eq 2 -o $c -eq 3 ] && echo ok
ok ####it is printing this value bcoz you have set the variable to match, it doesn't matter condition is wrong or right but there is something to match.

要解决此问题,您可以在开始时使用一个if条件,在没有值时指定一个伪值。

您的整个表达式可以简化为:

function help () {
    printf "%s\n" "help is on it's way."
}

[[ $# -eq 0 || "$*" = "--help" ]] && help ; echo "done." && exit 0 ;

这将检查参数的总和是否为零,或者参数是否等于“-help”。如果这两件事中的任何一件是真的,那么它将进入
help
函数,否则回显“done”并退出。

使用更多的引号:
[$#-eq 1-a“$1”=“--help”-o$#-eq 0]
(请参阅变量扩展
“$1”周围的引号)
?)。@gniourf\u gniourf:为什么不直接使用
$#-eq 0-o“$*”=“--help”
?@l'l'l:我的观点只是关于引号。下面有更好的答案
@gniourf\u gniourf,谢谢你,你的引号是对的,我完全忘记了,我想你是第一个提到的。如果你把答案写下来,我会把你的答案打勾。
$1
应该被引用,因为答案是空的值或带空格的值会导致测试失败,因为在分词后参数的数量不正确。在两种情况下重用
$\said是对的。问题是我没有引用$1。谢谢你:“[[]]构造是特殊的shell语法,不是命令,并且里面的内容不受分词的约束”,这可能不完全正确。在shellcheck.net中,使用未引用的
$@
$*
[]]内部使用时会提示此警告
,所以这可能是一个例外。@Bash手册中的l'l'l:“[[和]]之间的单词不进行分词和文件名扩展。”有趣的是,shellcheck.net上出现了警告;我想知道是否应该报告这一点。仍然来自手册中关于
$@
的部分:“当展开发生在双引号内时,每个参数展开为一个单独的字。”。这种宝贵的行为,也可用于数组展开,一开始可能有点违反直觉,因为双引号通常包含一个将被视为单个字的字符串。应该理解为”展开所有参数,但确保每个参数保持为单个单词,方法是不将其提交到单词拆分。在shellcheck中,当尝试使用
[[$@]]
时,它返回
^--SC2199:数组隐式连接到[[[]]。使用循环(或显式*而不是@)。
,然后在使用
[$*]时
它返回
^--SC2048:使用“$@”(带引号)来防止空白问题。
,因此有点混乱。这在@l'l'l工作得很好。我不太理解[]和[]之间的区别。据我所知[]是命令测试的缩写。@Adriano_epifas:简而言之,
[
是bash对
的改进[
表示法。下面是一个详细的比较:。示例:不客气!
[
[
实际上是“测试命令”,而不是前面提到的“表示法”;