在 Bash 中,是否可以将带有正确引用的选项列表的变量传递给命令,并且不将其在引号内的空格上分割? IOW,这个脚本:
MYCONFIG="--hi FOO=bar 'X=ABC 123'"
printf '[%s]\n' $MYCONFIG
输出:
[--hi]
[FOO=bar]
['X=ABC]
[123']
我希望它输出的是
[--hi]
[FOO=bar]
['X=ABC 123']
我意识到这可以用数组来完成或者作为一个函数,但我正在与已经依赖于创建字符串变量来保存参数的脚本。不可能是替换为函数因为该脚本的其他用户会收到错误。
是否可以使用正确的引号构造一个字符串,以防止引号字符串内的空格被破坏?
如果失败,我该如何修改剧本支持数组配置和现有字符串配置,也许将其中之一转换为另一种?
答案1
在 中zsh
,你会这样做:
$ MYCONFIG="--hi FOO=bar 'X=ABC 123'"
$ printf '[%s]\n' ${(z)MYCONFIG}
[--hi]
[FOO=bar]
['X=ABC 123']
$ printf '[%s]\n' "${(Q@)${(z)MYCONFIG}}"
[--hi]
[FOO=bar]
[X=ABC 123]
其中z
参数扩展标志使用 shell 标记化来中断输入(请注意,它是根据 zsh 语法,该标志也可以使用标志 wrt 注释或换行符处理z
进行调整,请参阅详细信息),并且剥离一级引用。Z
info zsh flags
Q
在 中bash
,你总是可以这样做:
readarray -td '' words < <(
export MYCONFIG
zsh -c 'print -rNC1 -- ${(z)MYCONFIG}'
)
printf '[%s]\n' "${words[@]}"
进行zsh
标记化并将单词传递给bash
NUL 分隔。
在这种情况下添加Q
标志可能会出现问题,就像$MYCONFIG
contains 一样$'\0'
,这会添加额外的 NUL。但无论如何,与变量内容中不能有 NULbash
相反zsh
,您不妨zsh
删除它们:
readarray -td '' words < <(
export MYCONFIG
zsh -c '
quoted_words=( ${(z)MYCONFIG} )
unquoted_words=( "${(Q@)quoted_words}" )
without_nul=( "${(@)unquoted_words//$'\''\0'\''}" )
print -rNC1 -- "${without_nul}"
'
)
答案2
稍作调整(必须牺牲单引号):
xargs -n1 printf "[%s]\n" <<<"$MYCONFIG"
[--hi]
[FOO=bar]
[X=ABC 123]
该xargs
实用程序能够通过-n
标志来区分参数。不幸的是,该-I
标志不允许通过不带引号的空格进行分割。