【问题标题】:How can I escape double quotes in the system command in this perl oneliner?如何在这个 perl one liner 的系统命令中转义双引号?
【发布时间】:2019-08-18 15:49:31
【问题描述】:

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

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

不使用\" 转义序列,如下所示:https://stackoverflow.com/a/1250279/3367247

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

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

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

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

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

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

这些都不起作用。有没有办法以链接答案的方式实现这一点?

编辑:我需要在 echo 命令中的 $_ 周围加上双引号,因为 $_ 中的字符串包含 括号,而不是因为它包含空格,就像我最初想的那样。

【问题讨论】:

  • perl -lane 'system(qq/echo "$_"/)'?
  • 您还应该考虑向系统传递参数的列表。这样,您不必调用 shell 并且引用不再是问题:system('/bin/echo', $_) -- perldoc.perl.org/functions/system.html
  • 谢谢@Shawn,我想我的问题更多是关于理解 bash 语法,而不是寻求最好的 perl 解决方案(当然,总是欢迎新的 perl 知识)。阅读链接的答案后,我以为我了解单/双引号的工作原理,但在这种情况下它不够。
  • @glennjackman 我不知道你可以打电话给system 并提供一份名单,谢谢。
  • 第二个例子:你不能使用单引号,因为$_是一个perl变量,需要在字符串中插入双引号

标签: bash perl syntax quoting


【解决方案1】:

我想发布一些我从有用的 cmets 和接受的答案中收集到的见解(谢谢大家!)。在我提出的原始命令中: $ 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 的字面值,在 $_ 周围(将通过外部 @ 987654331@s,在被发送到 bash 之前)。现在有两种方法可以完成这个

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

    (a-ii) 使用qq 运算符,它将赋予perl 字符串中"s 的特殊状态降级,然后可以将其用作普通字符:qq(echo "$_")

    (b) - 或者 - 生成最终 bash 命令的另一种方法是在 @Håkon 在他的回答中建议的 system 命令中使用 引号: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 调用中(然后您可以将文件名替换为 $_) .

【讨论】:

    【解决方案2】:

    我想了解如何在系统命令中转义引号 以下 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 $_")
    

    可以正常工作,或者您可以按照 cmets 中的建议进行操作:

    system(qq/echo "$_"/)
    

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

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

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

    system('echo ' . $_)
    

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

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

    或(使用双引号):

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

    【讨论】:

    • 事实证明我 确实 在 echo 命令中需要双引号 - 但不是因为 perl 字符串包含空格,正如我最初认为的那样。这是因为它包含括号。所以系统的单引号形式需要改为system('echo "' . $_ . '"')。而 shell 的单引号转义序列来适应这种情况变得非常令人麻木,哈哈。
    猜你喜欢
    • 2015-05-16
    • 2014-03-19
    • 1970-01-01
    • 2014-01-21
    • 1970-01-01
    • 2014-05-08
    • 1970-01-01
    • 2021-03-15
    • 2016-11-22
    相关资源
    最近更新 更多