`set -u`(nounset)vs检查我是否有参​​数

时间:2017-04-30 14:49:31

标签: bash

我正试图改进这个nasty old script。我找到了一个未定义的变量错误来修复,所以我添加了set -u以捕获任何类似的错误。

由于此代码,我得到" $ 1"的未定义变量错误

if [ -z "$1" ]; then
     process "$command"

它只是想知道是否有参数。 (传递空字符串时的行为作为第一个参数不是预期的。如果我们碰巧也解决这个问题,它将不会成为问题。)

set -u一起运行时,检查我们是否有参数的好方法是什么?

如果我们更换" $ 1"上面的代码将无法正常工作与" $ @",因为特殊方式" $ @"当有多个参数时会扩展。

5 个答案:

答案 0 :(得分:8)

$#包含参数的数量,因此您可以在访问之前测试$1$2等是否存在。

if (( $# == 0 )); then
    # no arguments
else
    # have arguments
fi;

答案 1 :(得分:6)

您可以通过在参数扩展中设置默认值来忽略set -u引起的自动退出:

#!/bin/sh
set -u
if [ -z "${1-}" ] ; then
    echo "\$1 not set or empty"
    exit 1
fi
echo "$2"    # this will crash if $2 is unset

语法为${parameter-default},如果未设置命名参数,则给出字符串default,否则给出参数值。同样,如果命名参数未设置或为空,${parameter:-default}会给default。上面,我们只使用了一个空的默认值。 (${1:-}在这里会是相同的,因为我们只是将空值更改为空值。)

那是feature of the POSIX shell并且也与其他变量一起使用,而不仅仅是位置参数。

如果您想区分未设置变量和空值,请使用${par+x}

if [ "${1+x}" != x ] ; then
    echo "\$1 is not set"
fi

答案 2 :(得分:2)

我个人的最爱:

if
  (($#))
then
  # We have at least one argument
fi

或者:

if
  ((!$#))
then
  # We have no argument
fi

答案 3 :(得分:0)

使用$#,参数的数量。这提供了对此帖子进行的最一致的编辑;点击加载处理空参数。

您可能还会看到使用"$*"。它与"$@"类似,但在有多个参数时会以不同方式展开。

a() {
    for i in "$@"; do echo $i; done
}
b() {
    for i in "$*"; do echo $i; done
}
c() {
    echo $#
}
echo "a()"
a "1 2" 3
echo "b()"
b "1 2" 3
echo "c()"
c "1 2" 3

# Result:
a()
1 2
3
b()
1 2 3
c()
2

答案 4 :(得分:0)

如果每个位置参数具有固定含义,您也可以使用此构造:

: ${1:?Missing first argument}

如果第一个位置参数未设置,则shell将打印"缺少第一个参数"作为错误消息并退出。否则,脚本的其余部分可以继续,安全地了解$1确实具有非空值。