Bash:如何在包含多个参数的变量内引用带有空格的 shell 参数而不使用数组?

Bash:如何在包含多个参数的变量内引用带有空格的 shell 参数而不使用数组?

在 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进行调整,请参阅详细信息),并且剥离一级引用。Zinfo zsh flagsQ

在 中bash,你总是可以这样做:

readarray -td '' words < <(
  export MYCONFIG
  zsh -c 'print -rNC1 -- ${(z)MYCONFIG}'
)
printf '[%s]\n' "${words[@]}"

进行zsh标记化并将单词传递给bashNUL 分隔。

在这种情况下添加Q标志可能会出现问题,就像$MYCONFIGcontains 一样$'\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标志不允许通过不带引号的空格进行分割。

相关内容