当我在bash脚本中传递包含[...]
的标志时,当我尝试使用getops
来获取值时,$OPTARG
给了我一个空字符串。
shopt -s nullglob
while getopts ":f:" opt; do
case $opt in
f)
str=$OPTARG
;;
esac
done
echo ${str}
运行脚本:
$ script.sh -f [0.0.0.0]
<blank line>
如何在脚本中重新获得原始值?
答案 0 :(得分:1)
假定较大的脚本中需要shopt -s nullglob
。
您可以使用shopt -s nullglob
shopt -u nullglob
shopt -s nullglob
shopt -u nullglob
while getopts ":f:" opt; do
case $opt in
f)
str=$OPTARG
;;
esac
done
echo ${str}
shopt -s nullglob
答案 1 :(得分:1)
简短摘要:用双引号引用您的变量引用。并使用shellcheck.net。
详细说明:当您使用一个不带双引号的变量时(例如echo ${str}
),shell会尝试将其值拆分为单词,并将任何类似于通配符表达式的内容扩展为匹配列表文件。对于[0.0.0.0]
,方括号使之成为通配符表达式,它将与字符“ 0”或“。”匹配。 (相当于[0.]
)。如果您有一个名为“ 0”的文件,它将扩展为该字符串。没有匹配的文件,通常不会扩展,但是设置nullglob
时,它会扩展为... null。
如果没有匹配的文件,则关闭nullglob
可解决此问题,但这并不是正确的方法。我记得(但现在找不到)关于一个脚本在一台特定计算机上失败的问题,事实证明,原因是一台计算机上碰巧有一个与括号表达式匹配的文件,且该文件的值未加引号
正确的解决方案是在变量引用周围加上双引号。这告诉外壳程序跳过分词和通配符扩展。这是一个交互式示例:
$ str='[0.0.0.0]' # Quotes aren't actually needed here, but they don't hurt
$ echo $str # This works without nullglob or a matching file
[0.0.0.0]
$ shopt -s nullglob
$ echo $str # This fails because of nullglob
$ shopt -u nullglob
$ touch 0
$ echo $str # This fails because of a matching file
0
$ echo "$str" # This just works, no matter whether file(s) match and/or nullglob is set
[0.0.0.0]
因此,在脚本中,只需将最后一行更改为:
echo "${str}"
请注意,case $opt in
或str=$OPTARG
中都不需要双引号,因为在这些特定上下文中的变量不受单词拆分或通配符扩展的影响。但是,IMO跟踪在哪些情况下可以安全地删除双引号是一件麻烦事,而不是值得的事,您应该将所有内容都用双引号
顺便说一句,shellcheck.net善于发现这样的常见错误;我建议您通过它来输入脚本,因为这可能不是您唯一遇到此问题的地方。