我正在尝试学习如何使用 getopts ,以便我可以拥有带有解析输入的脚本(尽管我认为 getopts 可能会更好)。我试图编写一个简单的脚本来返回分区使用百分比。问题是我的 bash 函数之一似乎不喜欢我$1
在函数内作为变量引用的函数。我引用的原因$1
是因为该get_percent
函数可以传递一个挂载点作为可选参数来显示,而不是显示所有挂载点。
剧本
#!/usr/bin/bash
set -e
set -u
set -o pipefail
get_percent(){
if [ -n "$1" ]
then
df -h $1 | tail -n +2 | awk '{ print $1,"\t",$5 }'
else
df -h | tail -n +2 | awk '{ print $1,"\t",$5 }'
fi
}
usage(){
echo "script usage: $(basename $0) [-h] [-p] [-m mount_point]" >&2
}
# If the user doesn't supply any arguments, we run the script as normal
if [ $# -eq 0 ];
then
get_percent
exit 0
fi
# ...
输出
$ bash thing.sh
thing.sh: line 8: $1: unbound variable
$ bash -x thing.sh
+ set -e
+ set -u
+ set -o pipefail
+ '[' 0 -eq 0 ']'
+ get_percent
thing.sh: line 8: $1: unbound variable
答案1
set -u
如果您引用尚未设置的变量,将完全按照您的描述中止。您正在不带参数调用脚本,因此get_percent
正在不带参数调用,从而导致$1
未设置。
在调用函数之前检查这一点,或者使用默认扩展(如果尚未设置为其他内容,${1:-default}
则将扩展为其他内容)。default
答案2
这就是 的效果set -u
。
您可以检查$#
函数内部并避免引用$1
(如果未设置)。
您可以通过它$#
访问多个参数。在全局上下文中,它是脚本的参数数量,在函数中,它是函数的参数数量。
在问题的上下文中,它是
if [ $# -ge 1 ] && [ -n "$1" ]
then
df -h $1 | tail -n +2 | awk '{ print $1,"\t",$5 }'
else
df -h | tail -n +2 | awk '{ print $1,"\t",$5 }'
fi
请注意,您必须使用[ $# -ge 1 ] && [ -n "$1" ]
and not [ $# -ge 1 -a -n "$1" ]
,因为它会首先评估$1
然后检查$#
。
答案3
其他答案都提到了这是 的效果set -u
。其他答案都没有提到set -u
可以通过以下方式逆转set +u
:
$ echo $VAR # nothing echoed below as VAR is unset:
$ set -u
$ echo $VAR
bash: VAR: unbound variable
$ set +u
$ echo $VAR # nothing echoed below as VAR is unset:
答案4
因为这是你可以绕过对设置bash
的检查,只使用(是第一个参数,是所有参数;当用双引号引起来时,如果它没有值,它会完全消失,这可以避免它被 捕获):$1
"$@"
$1
$@
set -u
get_percent() {
df -h "$@" | awk 'NR>1 { printf "%s\t%s\n", $1, $5 }'
}
我还稍微调整了该行的其余部分,这样您输出的两个值之间就不会出现 {space}{tab}{space} ,但您只会得到一个 {tab} 。如果您确实想要两个不可见的空间,请更改awk
为使用printf "%s \t %s\n", $1, $5
。