bash -c "echo 'hello world!'"
(我知道可以直接使用
echo
或Write-Host
,但我需要使用bash -c
),并且我希望hello
被单引号包围,world
被双引号包围。换句话说,我想要以下输出:'hello' "world"!
我应该如何转义这些引号?
bash -c "echo 'hello world!'"
echo
或Write-Host
,但我需要使用bash -c
),并且我希望hello
被单引号包围,world
被双引号包围。换句话说,我想要以下输出:'hello' "world"!
我应该如何转义这些引号?
由于您正在调用程序(例如bash
),因此转义引号字符的“普通”规则不一定以“相同”的方式工作。 PowerShell不会解释字符串(通常遵循“普通”引号规则),而是将参数传递给程序。这是以完全不同的方式解释的。
简而言之,要转义引号字符,需要使用以下命令:
bash -c "echo \'Hello\' \\\""World\\\""!"
输出:
'Hello' "World"!
HAL9256@HAL9000:~$ echo 'Hello' "World"!
Hello World!
没有引号。哦,是的!我必须转义它们。在 bash
中,我必须用反斜杠(\
)来转义它们:
HAL9256@HAL9000:~$ echo \'Hello\' \"World\"!
'Hello' "World"!
我们需要使用单个反斜杠来正确转义bash
中的引号。因此,让我们将其插入到PowerShell中:
PS C:\> bash -c "echo \'Hello\' \"World\"!"
/bin/bash: -c: line 0: unexpected EOF while looking for matching `"'
/bin/bash: -c: line 1: syntax error: unexpected end of file
那不起作用。哦,对了,在PowerShell中,我们必须使用反引号(`)转义双引号,因为它们在一组双引号内:
PS C:\> bash -c "echo \'Hello\' \`"World\`"!"
'Hello' World!
好的,这没有出现错误,但仍然不是我们想要的。引号仍然没有被正确转义。烦死了。 这就是你开始打100种不同字符组合来找到正确组合的地方 ;-).
或者,让我们回到bash
并找出可能发生的事情。首先,让我们记住正在echo
的字符串被解释为字符串。因此,让我们在我们的echo语句周围放置双引号,以便它被视为字符串,并查看它的作用。请记住,我们希望从中得到的输出与早期的bash
命令相同,具有反斜杠:
HAL9256@HAL9000:~$ echo "\'Hello\' \"World\"!"
\'Hello\' "World"!
最终,我们想要发送给 bash
的是带有反斜杠的原始字符串。在这里,我们可以看到反斜杠正在转义双引号并消失。因此,需要添加更多的反斜杠:
HAL9256@HAL9000:~$ echo "\'Hello\' \\"World\\"!"
\'Hello\' \World\!
哦,太好了。我们成功避开了反斜杠。就像电影《盗梦空间》一样,不断添加转义字符直到它能正常工作...
HAL9256@HAL9000:~$ echo "\'Hello\' \\\"World\\\"!"
\'Hello\' \"World\"!
好的,我们现在有了输出结果。现在我们需要将其输入到PowerShell中:
PS C:\> bash -c "echo \'Hello\' \\\"World\\\"!"
/bin/bash: -c: line 0: unexpected EOF while looking for matching `"'
/bin/bash: -c: line 1: syntax error: unexpected end of file
哦!是之前的同样错误。在PowerShell中,我们必须记得用反引号转义双引号:
PS C:\> bash -c "echo \'Hello\' \\\`"World\\\`"!"
'Hello' "World"!
成功了!只需要进行大量的转义,无论是在bash还是PowerShell中。另一种方法,我认为更易于理解的方式是在双引号内使用两个双引号来进行转义,而不是使用反引号,如下所示:
PS C:\> bash -c "echo \'Hello\' \\\""World\\\""!"
'Hello' "World"!
HAL9256的答案很有帮助,但是让我试着用不同的方式来表述这个问题:
如果你从bash
本身运行命令,为了获得所需的逐字输出,你的命令应该像这样:
# From Bash itself
$ bash -c "echo \"'hello' \\\"world\\\"!\""
'hello' "world"!
\
作为转义字符,意味着新的bash
实例将以下文本作为其-c
参数:echo "'hello' \"world\"!"
echo
参数作为整体被包含在(最初\
转义的)"..."
中,以确保鲁棒性:如果world
是world & space
,则命令会中断; 同样,world class
将变成world class
(由于shell扩展而进行的空格规范化)。\
字符,因为涉及到2层转义:
为了调用shell(在本例中也是bash
),以确保输入字符串在语法上有效:\"
嵌入一个单个的"
,而\\
是单个的\
。
针对目标shell(bash
),以便结果字符串在语法上对于它是有效的,考虑到在这种情况下将解析为命令的结果字符串。
`
,PowerShell的转义字符,而不是\
。# SHOULD work, but DOESN'T as of PowerShell 7.0
PS> bash -c "echo `"'hello' \`"world\`"!`""
hello # !! WRONG output.
"echo `"'hello' \`"world\`"!`""
,则会发现它会正确地生成verbatim字符串,就像上面展示的那样(echo "'hello' \"world\"!"
)。但是,这种方法不起作用的原因在于 PowerShell将参数传递给外部程序时,始终存在问题,特别是在处理嵌入式双引号时:这个答案提供了一个概述,但简单来说,截至PowerShell 7.0:除了满足PowerShell的自己的语法要求(如果您调用PowerShell命令,则足够),您必须额外\
转义嵌入式"
字符,以便传递给外部程序的参数。因此:# OK, but the manual \-escaping shouldn't be necessary.
PS> bash -c "echo \`"'hello' \\\`"world\\\`"!\`""
'hello' "world"!
PS> bash -c 'echo "hi, there"'
hi, # !! " were stripped, so bash only saw `echo hi,` as the command string,
# !! and `there` as a separate argument.
PS> /bin/echo '{ "foo": "bar" }' # Try to pass a JSON string
{ foo: bar } # !! BROKEN JSON