我看过关于这个问题的类似帖子,但不知道该如何让执行的代码符合正确的格式,即 foo --bar \'a='b'\'。我最好的尝试是...
我看过关于这个问题的类似帖子,但不知道该如何让执行的代码符合正确的格式,而正确的格式应该是 foo --bar "a='b'"
。我最好的尝试是
#!/bin/bash -x
bar='--bar ''"''a='"'"'b'"'"'"'
cmd=(foo $bar)
echo ${cmd[@]}
eval ${cmd[@]}
的输出对于 来说是正确的 echo
,但对于 来说不正确 eval
+ bar='--bar "a='\''b'\''"'
+ cmd=(foo $bar)
+ echo foo --bar '"a='\''b'\''"'
foo --bar "a='b'"
+ eval foo --bar '"a='\''b'\''"'
++ foo --bar 'a='\''b'\'''
使用该选项执行命令的正确方法是什么?
符合 BashFAQ #50 的 :
#!/usr/bin/env bash
bar=( --bar a="b" )
cmd=(foo "${bar[@]}" )
printf '%q ' "${cmd[@]}" && echo # print code equivalent to the command we're about to run
"${cmd[@]}" # actually run this code
奖励:您的调试输出并不能证明您的想法。
"a='b'"
和 'a='\''b'\'''
是引用 同一字符串的 .
为了证明这一点:
printf '%s\n' "a='b'" | md5sum -
printf '%s\n' 'a='\''b'\''' | md5sum -
...输出如下:
7f183df5823cf51ec42a3d4d913595d7 -
7f183df5823cf51ec42a3d4d913595d7 -
在您的代码中, echo $foo
和 eval $foo
的参数的解析方式没有任何不同
为什么会这样?因为语法引号不是实际运行的命令的一部分;在 shell 使用它们确定如何逐个字符地解释命令行后,它们会被删除。
那么,让我们分解一下 set -x
向您展示的内容:
'a='\''b'\'''
...由以下文字字符串连接在一起组成:
a=
(在单引号上下文中,以单引号括起来并结束)
'
(在未加引号的上下文中,通过其前面的反斜杠进行转义)
b
(在单引号上下文中,以单引号括起来并结束)
'
(在未引用的上下文中)
...其他一切都是 语法性的 ,对 shell 有意义,但从未传递给程序 foo
.