如何在这个perl one liner中删除系统命令中的双引号?

问题描述 投票:2回答:2

为了我的启发,我想了解如何在以下perl oneliner中的system命令中转义引号:

$ ls -p | grep -v / | perl -lane 'system("echo \"$_\"");'

没有使用\"逃逸序列,以这里显示的方式:https://stackoverflow.com/a/1250279/3367247

(显然这个命令没有任何用处;它只打印出有空格的文件名。但它可以解释我的问题。)

我尝试了以下(原谅图像,但我发现突出显示最容易破译引用):

  1. 带双引号的系统命令:system("echo "$_"") enter image description here

代码:$ ls -p | grep -v / | perl -lane 'system("echo ''"''$_''"''");'

  1. 带单引号的系统命令:system('echo "$_"') enter image description here

代码:$ ls -p | grep -v / | perl -lane 'system('"'"'echo "$_"'"'"');'

这些都不奏效。有没有办法以链接答案的方式实现这一目标?

编辑:我需要在echo命令中围绕$_使用双引号,因为$_中的字符串包含括号,而不是因为它包含空格,正如我原先想的那样。

bash perl syntax quoting
2个回答
0
投票

我想了解如何在以下perl oneliner中的系统命令中转义引号:

$ ls -p | grep -v / | perl -lane 'system("echo \"$_\"");'

没有使用“逃脱序列,以这里显示的方式:[...]

这些示例用于转义单引号,您的示例使用双引号\"$_\"。在Bash中,单引号内的所有内容都是字面上的(单引号本身除外),双引号内的情况也是如此。例如,双引号内的$不是文字$,而是表示要遵循变量扩展。

现在,在您的命令中有三个级别的引用解释。

  • 首先是外壳(命令行): perl -lane 'system("echo \"$_\"");'
  • 那么perl解释器: system("echo \"$_\");
  • 然后是第二个shell(这里使用Bash): echo "xxx"

其中xxx$_剧本中perl的扩张

您的命令不包含任何内部单引号,因此无需使用Bash引用构造来转义单引号,例如

It's fine  -> 'It'"'"'s fine'

要么

It's fine  -> 'It'\''s fine'

此外,您需要在perl脚本中转​​义双引号

system("echo \"$_\"")

因为它们在双引号内,或者你可以删除它们,因为echo在这里不需要双引号:

system("echo $_")

可以正常工作,或者你可以按照评论中的建议做:

system(qq/echo "$_"/)

或使用LIST form of system with more than one argument

system("/bin/echo", $_)

但是,如果您想使用单引号,例如:

system('echo ' . $_)

你需要调用shell的单引号转义:

'system('"'"'echo ''"' . $_)'

或(使用双引号):

"system('echo ' . "'$'"_)"

1
投票

我想发表一些我从有用的评论和接受的答案中收集的见解(谢谢大家!)。在我提出的原始命令中:$ ls -p | grep -v / | perl -lane 'system("echo \"$_\"");'有两个解释器:bash和perl,发挥作用:

  1. 由bash解释的原始命令不接触(唯一的一对)单引号内的任何内容(即-lane之后的所有内容)并将其作为脚本完整地传递给perl。
  2. 然后perl解释器处理此脚本,该脚本由单个system命令组成。 perl解释器负责生成最终的echo命令行,该命令行被抛回bash进行解释。这个最终的bash命令需要从$_动态生成。有两种方法可以做到这一点: (a)使用带双引号的系统命令,以便插入$_ [即system("echo $_")]但是请注意,回声的字符串需要有围绕它的"s,因为它可能包含括号。所以我们需要perl在这个最终的bash命令字符串中发出文字"s,围绕$_(在被发送到bash之前,它将通过外部"s扩展)。现在有两种方法可以实现此目的: (a-i)使用"逃离\以发出字面引号:"echo \"$_\"" (a-ii)使用qq运算符,它将perz字符串中的"s特殊状态降级,然后可以用作普通字符:qq(echo "$_")。 (b) - 或者 - 生成最终bash命令的另一种方法是使用system命令中的单引号,如@Håkon在他的回答中所建议的那样:system('echo ' . $_)。但是如前所述,我们仍然需要围绕$_的引号,所以我们需要将其更改为:system('echo "' . $_ . '"')。现在,任务减少到计算bash的单引号转义以确保perl看到此字符串。

perl命令的最终形式是:

2-a-i:perl -lane 'system("echo \"$_\"");'

2-a-ii:perl -lane 'system(qq/echo "$_"/);'

最后:

2-b:perl -lane 'system('"'"'echo "'"'"'.$_.'"'"'"'"'"');'

这种对's和"s的歪曲就是我要达到的目标,所以使命已经完成了! :d

编辑说明:从一个实用的可用性pov,qq形式似乎最适合将最终的,所需的bash命令粘贴到perl system调用中(然后你可以用$_替换文件名)。

© www.soinside.com 2019 - 2024. All rights reserved.