Linux Bash脚本:[test]中的参数太多
我有下面的bash脚本: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)时,它会失败,因为“参数太多”
#!/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对的改进[
表示法。下面是一个详细的比较:。示例:不客气![
和[
实际上是“测试命令”,而不是前面提到的“表示法”;