Tim*_*iam 42 scripting bash shell-script
我正在尝试学习如何使用 getopts 以便我可以使用解析输入的脚本(尽管我认为 getopts 可能会更好)。我正在尝试编写一个简单的脚本来返回分区使用百分比。问题是我的 bash 函数之一似乎不喜欢我$1
在函数中作为变量引用。我引用的原因$1
是因为该get_percent
函数可以将挂载点作为可选参数传递给 display 而不是所有挂载点。
#!/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
# ...
Run Code Online (Sandbox Code Playgroud)
$ 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
Run Code Online (Sandbox Code Playgroud)
Dop*_*oti 63
set -u
如果您引用尚未设置的变量,将完全按照您的描述中止。您正在不带参数调用脚本,因此在不带参数的情况下调用脚本get_percent
,导致未$1
设置。
在调用您的函数之前检查这一点,或者使用默认扩展(如果尚未设置为其他内容,${1-default}
将扩展为default
)。
Ral*_*edl 11
这是 的效果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
Run Code Online (Sandbox Code Playgroud)
请注意,您必须使用[ $# -ge 1 ] && [ -n "$1" ]
and not [ $# -ge 1 -a -n "$1" ]
,因为那将首先评估$1
然后检查$#
。
Jas*_*sha 10
其他答案都提到了这是 的效果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:
Run Code Online (Sandbox Code Playgroud)
使用脚本中的“set -u”,任何对未设置变量的引用都会导致错误,特别是测试它是否有值,这就是脚本正在执行的操作。
以下函数将测试未设置的变量,而不会触发 set -u:
if:IsSet() {
[[ ${!1-x} == x ]] && return 1 || return 0
}
Run Code Online (Sandbox Code Playgroud)
使用它:
if:IsSet someVariableName || echo "someVariableName is not set"
至于实际的函数,测试是否传入了参数,而不是测试是否为空。这将避免未设置变量的问题,而无需采取任何特殊步骤,例如测试变量是否有值。
get_percent(){
if [ ${#1} -eq 0 ]
Run Code Online (Sandbox Code Playgroud)
顺便说一句:函数名称中的冒号只是一个字符。它在 Bash 中的函数名称中有效,如 %、}、{、[ 和其他一些:-)
因为这是你可以绕过对设置的bash
检查,只使用(是第一个参数,是所有参数;当用双引号引起来时,如果它没有值,它会完全消失,这可以避免它被 捕获):$1
"$@"
$1
$@
set -u
get_percent() {
df -h "$@" | awk 'NR>1 { printf "%s\t%s\n", $1, $5 }'
}
Run Code Online (Sandbox Code Playgroud)
我还稍微调整了该行的其余部分,这样您输出的两个值之间就不会出现 {space}{tab}{space} ,但您只会得到一个 {tab} 。如果您确实想要两个不可见的空间,请更改awk
为使用printf "%s \t %s\n", $1, $5
。