使用从 args 读取的命令和“未终止的引号字符串”/“意外的 EOF”从 sh (dash) 调用 bash

使用从 args 读取的命令和“未终止的引号字符串”/“意外的 EOF”从 sh (dash) 调用 bash

只是想记录下来:我正在尝试一些非常简单的事情 - 设置环境变量bash,然后将其打印出来:

$ bash -c "a=1; echo a$a;"
a
$ bash -c "a=1; echo a\$a;"
a1

现在我想要同样的东西,但被称为sh(在我的系统上,ls -la $(which sh)给出/bin/sh -> dash)的参数:

$ sh -c "bash -c "a=1; echo a\$a;""
a$a

# obviously I have to escape inner quotes:

$ sh -c "bash -c \"a=1; echo a\$a;\""
a

# escape the dollar once more?

$ sh -c "bash -c \"a=1; echo a\\$a\" "
sh: Syntax error: Unterminated quoted string

# nope... inner single quotes, then?

$ sh -c "bash -c 'a=1; echo a$a;'"
a

# nope... escape the single quotes?

$ sh -c "bash -c \'a=1; echo a$a;\'"
bash: -c: line 0: unexpected EOF while looking for matching `''
bash: -c: line 1: syntax error: unexpected end of file
a
sh: ': not found

# nope... escape the dollar too?

$ sh -c "bash -c \'a=1; echo a\$a;\'"
bash: -c: line 0: unexpected EOF while looking for matching `''
bash: -c: line 1: syntax error: unexpected end of file
a
sh: ': not found

所以,我的问题是 - 转义的正确语法是什么,这样sh -c [bash -c ...]可以得到与刚才相同的结果bash -c ...

答案1

在单引号内,没有任何字符具有特殊含义。双引号内,"\$`有特殊含义。从外向内计算:首先弄清楚外壳是由什么弦组成的,然后是内壳将由它组成。

例如,假设变量a没有在外壳中定义,则

sh -c "bash -c \"a=1; echo a\$a;\""

外壳看到一个双引号字符串,它扩展为bash -c "a=1; echo a$a;",并且该字符串被传递给中间sh。将其解析为使用两个参数和sh的调用,后者是由于扩展未定义变量的双引号字符串而产生的。bash-ca=1; echo a;"a=1; echo a$a;"a

如果您进行此分析,您会发现获得您想要的东西的一种方法是"a=1; echo a\$a;"在这个阶段获得。为了获得这个额外的反斜杠,您需要在原始文件中添加两个反斜杠,因为双引号内已经有一个 shell 扩展阶段。二加一等于三。

sh -c "bash -c \"a=1; echo a\\\$a;\""

对外部字符串使用单引号会更简单,因为您不想扩展其中的任何内容。

sh -c 'bash -c "a=1; echo a\$a;"'

由于您不想在bashsh任一方调用时展开任何内容,因此也可以在此处使用单引号。您不能在单引号字符串中放入单引号,但有一种方法可以模拟这种情况: put '\''。形式上,这会终止单引号文字,附加一个单引号文字,并开始一个新的单引号文字,但您可以将四字符序列'\''视为将单引号放入单引号字符串中的一种方法。

sh -c 'bash -c '\''a=1; echo a$a;'\'''

你可以''在最后省略它,它不太系统,但更容易看到。

sh -c 'bash -c '\''a=1; echo a$a;'\'

单引号在双引号内并不特殊,因此在编写时需要在美元前面加上反斜杠,以防止在外壳中"bash -c 'a=1; echo a\$a;'"扩展。$a

答案2

好吧,我找到了一些可以工作的(注意,这是 Ubuntu 11.04):

$ sh -c "bash -c 'a=1; echo a\$a \'"
a1
$ sh -c "bash -c 'a=1; echo a\$a;'"
a1

...看起来,只要第一个单引号没有转义,并且美元也被转义 - 它就有效,无论最后的单引号是否被转义!这仍然让我很困惑......

相关内容