如何在此 perl oneliner 的系统命令中转义双引号?

How can I escape double quotes in the system command in this perl oneliner?

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

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

不使用 \" 转义序列,采用此处显示的方式:

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

我尝试了以下方法(请原谅图片,但我发现突出显示最容易破译引文):

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

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

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

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

这些都不起作用。有没有办法按照链接答案的方式来完成这个?

编辑:我需要在 echo 命令中用双引号将 $_ 括起来,因为 $_ 中的字符串包含 圆括号 ,而不是因为它包含空格,和我原来想的一样。

I'd like to find out how to escape quotes within the system command in the following perl oneliner:

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

without using the \" escape sequence, in the manner shown here: [...]

这些示例用于转义 引号,您的示例使用 引号 \"$_\"。在 Bash 中,单引号内的所有内容均按字面意义(单引号本身除外),双引号内的内容并非如此。例如,双引号内的 $ 不是文字 $,而是表示后面要进行变量扩展。

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

  • 首先外shell(命令行):

    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 ' . "'$'"_)"

我想 post 从有用的评论和已接受的答案中收集到一些见解(谢谢大家!)。在我提出的原始命令中: $ 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 之前,将通过外部 " 扩展)。现在有两种方法可以完成this:

    (a-i) 使用 \ 转义 " 以发出文字引号:"echo \"$_\""

    (a-ii) 使用qq运算符,将"s在perl字符串中的特殊地位降级,可以作为普通字符使用: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

编辑说明:从实用的可用性角度来看,qq 形式似乎最适合将最终的、所需的 bash 命令粘贴到 perl system 调用中(而你然后可以用 $_).

替换文件名