我尝试了许多不同的解决方案,例如Greg(又名GreyCat)的Wiki上的BashFAQ / 096是一个很好的资源,包括背景信息和替代方法。总的来说,我发现以下两项是最易读的(在工作中):
从Bash 4.4开始(据我从NEWS得知),可以像这样使用参数扩展 @Q
:
adb sh -c "other_tool -a -b ${*@Q}"
请注意,我$*
在这里使用而不是$@
因为您希望"other_tool -a -b ${*@Q}"
成为一个单个字符串,而不是每个传递的参数一个字符串。
如果要对bash数组变量执行相同操作,则需要语法${ARRAY[*]@Q}
(在引号内)。
如果您没有可用的Bash 4.4或更高版本,或者不确定,这是我的首选解决方案:
function escapeBashArgs() {
local arg separator=""
for arg
do
printf "%s%q" "$separator" "$arg"
separator=" "
done
}
adb sh -c "other_tool -a -b $(escapeBashArgs "$@")"
请注意,此处您需要使用"$@"
而不是$@
或"$*"
或,$*
因为您不希望在参数内进行单词拆分,因此无法使用不带引号的变体,并且您希望保留参数的数量,因此"$*"
无法使用,因为它将连接在一起一个字符串的所有参数。然后,该函数以单个字符串返回所有参数。
如果您不关心第一个参数前面的额外空间,则可以将printf
格式字符串更改为" %q"
并删除该separator
变量。或者,您可以使用Gordon Davissons answer中的单线。
该解决方案适用于我可能提出的所有情况,尤其是:
- 无参数:
escapeBashArgs
→ 无
- 空参数:
escapeBashArgs "" ""
→'' ''
- 仅带有空格的参数:
escapeBashArgs " " " "
→ ' ' ' '
或\ \ \ \ \
(此网站渲染器占用了最后一个空格)
- 具有特殊间距和换行符的参数:
escapeBashArgs "a b" c\ d "arg with
newline"
→ 'a b' 'c d' $'arg with\nnewline'
或a\ \ \ \ \ \ b c\ d $'arg with\nnewline'
(换行符位于with
和之间newline
,其他位置是由于该站点上的换行而引起的)
- 具有特殊字符的参数:
escapeBashArgs '$"'\''({:})'
→ '$"'\''({:})'
或\$\"\'\(\{:\}\)
- 来自jcayzacs的示例答案:
escapeBashArgs x/\ \ \"b\"/aaaaa/\'xxx\ yyyy\'/zz\"offf\"
→ 'x/ "b"/aaaaa/'\''xxx yyyy'\''/zz"offf"'
或x/\ \ \"b\"/aaaaa/\'xxx\ yyyy\'/zz\"offf\"
(使用GNU bash 5.0.3(1)-发行版进行了测试。)