如果标志值包含括号,则 getopt $OPTARG 为空
getops $OPTARG is empty if flag value contains brackets
当我将包含 [...]
的标志传递给我的 bash 脚本时,当我尝试使用 $OPTARG
获取值时 getops
给我一个空字符串。
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>
如何在脚本中取回原始值?
假设在更大的脚本中需要 shopt -s nullglob
。
您可以使用 shopt -u nullglob
暂时禁用 shopt -s 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
简短摘要:双引号变量引用。并使用 shellcheck.net.
详细解释:当您使用一个没有双引号的变量时(例如 echo ${str}
),shell 会尝试将其值拆分为单词,并扩展任何看起来像通配符的内容表达式到匹配文件列表中。在 [0.0.0.0]
的情况下,方括号使其成为匹配字符“0”或“.”的通配符表达式。 (相当于 [0.]
)。如果您有一个名为“0”的文件,它将扩展为该字符串。如果没有匹配的文件,它通常不会展开,但设置 nullglob
后它会展开为 ... null.
如果没有匹配的文件,关闭 nullglob
可以解决问题,但这并不是真正正确的方法。我记得(但现在找不到)我们有一个关于在一台特定计算机上失败的脚本的问题,结果证明原因是一台计算机恰好有一个文件与未引用变量值中的括号表达式匹配.
正确的解决方案是在变量引用周围加上双引号。这告诉 shell 跳过分词和通配符扩展。这是一个交互式示例:
$ 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 擅长发现这样的常见错误;我建议通过它来提供您的脚本,因为这可能不是您遇到此问题的唯一地方。
当我将包含 [...]
的标志传递给我的 bash 脚本时,当我尝试使用 $OPTARG
获取值时 getops
给我一个空字符串。
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>
如何在脚本中取回原始值?
假设在更大的脚本中需要 shopt -s nullglob
。
您可以使用 shopt -u nullglob
shopt -s 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
简短摘要:双引号变量引用。并使用 shellcheck.net.
详细解释:当您使用一个没有双引号的变量时(例如 echo ${str}
),shell 会尝试将其值拆分为单词,并扩展任何看起来像通配符的内容表达式到匹配文件列表中。在 [0.0.0.0]
的情况下,方括号使其成为匹配字符“0”或“.”的通配符表达式。 (相当于 [0.]
)。如果您有一个名为“0”的文件,它将扩展为该字符串。如果没有匹配的文件,它通常不会展开,但设置 nullglob
后它会展开为 ... null.
如果没有匹配的文件,关闭 nullglob
可以解决问题,但这并不是真正正确的方法。我记得(但现在找不到)我们有一个关于在一台特定计算机上失败的脚本的问题,结果证明原因是一台计算机恰好有一个文件与未引用变量值中的括号表达式匹配.
正确的解决方案是在变量引用周围加上双引号。这告诉 shell 跳过分词和通配符扩展。这是一个交互式示例:
$ 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 擅长发现这样的常见错误;我建议通过它来提供您的脚本,因为这可能不是您遇到此问题的唯一地方。