如何在Bash中测试位置参数是否已设置?

4

我不明白为什么下面这个函数无论我是否传入第一个位置参数,测试 [[ ! -v 1 ]] 都会失败:

shopt -os nounset

function foo {
  echo -n "$FUNCNAME: 1st positional parameter "
  [[ ! -v 1 ]] && echo "is missing." || echo is "\"$1\"."
}

我知道还有其他测试方法,但为什么这个特定的测试不起作用呢?


尝试使用[[ -v SHELL ]]; echo $?命令。 -z无法使用,因为存在shopt -os nounset配置。 - Tim Friske
可能它不能与整数一起使用,使用像“foo”这样的普通变量名称可以解决问题。 - Nihathrael
这个内容在我的bash 4.2手册中:-v varname 如果shell变量varname已设置(已分配一个值),则为True。 - dogbane
5
我认为位置参数不符合“shell变量”的条件,因此 -v 在其上不能起作用。 - German Garcia
1
对我来说,检查参数是否存在应该使用$#。另请参见https://dev59.com/F2bWa4cB1Zd3GeqPTiJb - German Garcia
显示剩余4条评论
4个回答

4
在这种情况下,您希望检查参数是否未设置。
has_1() {
  if [[ -z "${1+present}" ]]; then 
    echo "no first param"
  else
    echo "given: $1"
  fi
}

参数扩展 ${var+word} 仅在参数未设置时返回 "word" -- 即如果您传递一个空字符串,该函数将指示第一个参数已给出。


你的建议听起来很合理,因为它通过它的符号引用位置参数,并避免了bash在使用shopt -os nounset时失败。如果没有其他人能够解释为什么[[ ! -v 1 ]]不起作用,我将考虑这是一个错误 - Tim Friske
1
显然,-v无法用于位置参数: set -- bar; echo $1; [[ -v 1 ]] || echo no foo - glenn jackman
1
从Bash 5.1版本开始,它可以工作:https://dev59.com/KmrXa4cB1Zd3GeqPC8wO#65233119(请随意复制到您的答案中) - fedorqui

4

Bash 5.1有一种非常简单的方法来实现这个功能。如在发布说明中所述:

x. `test -v N'现在可以测试位置参数N是否设置。

因此,要检查第N个参数是否已设置,可以使用以下任一方式:

test -v N

[ -v N ]

看一个非常基本的例子:

test -v 1 && echo "1st parameter is set: '$1'"
[ -v 2 ] && echo "2nd parameter is set: '$2'"

查看一些示例:

bash-5.1$ bash script.sh ""
1st parameter is set: ''

bash-5.1$ bash script.sh a b
1st parameter is set: 'a'
2nd parameter is set: 'b'

bash-5.1$ bash script.sh ""
1st parameter is set: ''

bash-5.1$ bash script.sh "" bla
1st parameter is set: ''
2nd parameter is set: 'bla'

3
if [ "$#" -gt "0" ]; then echo 'ok'; else echo '0'; fi

我们已经有了这个答案,但作者删除了它,因为$#只是间接地测试第一个位置参数是否设置。此外,在他的答案中,他无法解释为什么[[ ! -v 1 ]]会失败。 - Tim Friske
我也不知道 -v 选项在 test 中的含义。 - alinsoar

1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接