如果标志值包含方括号,则getops $ OPTARG为空

时间:2019-03-26 12:37:09

标签: bash echo getopts

当我在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>

如何在脚本中重新获得原始值?

2 个答案:

答案 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 instr=$OPTARG中都不需要双引号,因为在这些特定上下文中的变量不受单词拆分或通配符扩展的影响。但是,IMO跟踪在哪些情况下可以安全地删除双引号是一件麻烦事,而不是值得的事,您应该将所有内容都用双引号

顺便说一句,shellcheck.net善于发现这样的常见错误;我建议您通过它来输入脚本,因为这可能不是您唯一遇到此问题的地方。

相关问题