【问题标题】:How can I escape code-like things in a Perl string?如何在 Perl 字符串中转义类似代码的内容?
【发布时间】:2011-01-20 14:43:17
【问题描述】:

$i=1; 而($i

EOT

    $i++;
}

产生错误:

在没有包或对象引用的情况下,无法在 borrar.pl 第 3 行调用方法“px”。

我怎样才能“逃避” if ?

谢谢。

【问题讨论】:

  • 我不知道那是什么,但肯定不是 Perl。
  • print/EOT 中的代码肯定不是,但这不是重点,我只需要将 print/EOT 中的内容写入标准输出;事实上,如果我删除“if”块,它会完美运行。
  • Doh -- 我错过了这些东西在一个大的heredoc中的事实。

标签: perl printing heredoc


【解决方案1】:

很难说这段代码应该完成什么,但也许您希望 println 语句中的外部美元符号保留在最终输出中?

println "\${px$i.name} / \${px$i.empr.to} OK"

通过该更改,我看到的无错误输出是:

def px1 = new E(user) 
if (!px1.hasErrors()) {
        println "${px1.name} / ${px1.empr.to} OK"
}

def px2 = new E(user) 
if (!px2.hasErrors()) {
        println "${px2.name} / ${px2.empr.to} OK"
}

【讨论】:

  • 该代码是一个更大的脚本的一部分,它加载一个 cvs 并从它的数据创建 groovy 类。问题是为什么 perl 编译器试图编译 print/EOT 中的块以及如何告诉它不要编译。(顺便说一句,感谢您的建议,但它没有用)
【解决方案2】:

命令行选项-MO=Deparse 向您展示了 Perl 在简化代码后如何解释您的代码(例如,将 heredocs 转换为 qq{} 块)。例如

$ perl -MO=Deparse test.pl
$i = 1;
while ($i < 3) {
    print qq[    def px$i = new E(user) \n    if (!px$i.hasErrors()) {\n            println "${$i->px . 'name';} / ${$i->px . 'empr' . 'to';} OK"\n    }\n\n];
    ++$i;
}

相关部分是:

println "${$i->px . 'name';} / ${$i->px . 'empr' . 'to';}

Perl 已将 ${px$i.name} 转换为 ${$i-&gt;px . 'name'}

在 perl 中,${...} 表示评估块内的任何内容,并将其视为symbolic reference(即变量名)或标量引用,然后取消引用以将其转回标量。因此 Perl 尝试执行这些块中的任何内容,将它们的内容视为 Perl 代码。这是因为您的heredoc,"EOT" 就像一个双引号字符串,并且插入了美元符号。

解决方案是:转义美元符号 ($ -> \$) 或使用单引号和连接而不是 heredocs。

【讨论】:

    【解决方案3】:

    这应该可以解决问题。

    println "${"px$i.name"} / ${"px$i.empr.to"} OK"
    println "px$i.name" / px$i.empr.to OK"
    

    【讨论】:

      【解决方案4】:

      如您所见,字符串的$px 部分正在被评估。你只需要逃避它:

      $i=1;
      while($i<3) {
          print << "EOT";
          def px$i = new E(user) 
          if (!px$i.hasErrors()) {
                  println "\${px$i.name} / \${px$i.empr.to} OK"
          }
      
      EOT
      
          $i++;
      }
      

      在“解析带引号的构造的血腥细节”下的perldoc perlop 阅读有关字符串转义的更多信息。

      【讨论】:

        【解决方案5】:
        my $format = << 'EOT';
        def px%d = new E(user)
            if (!px%d.hasErrors()) {
                    println "${px%d.name} / ${px%d.empr.to} OK"
            }
        EOT
        
        for my $i ( 1 .. 3 ) {
            printf $format, ($i) x 4;
        }
        

        【讨论】:

        • (+1) 有多种 heredocs 单引号是非插值的。另一种类型是反引号,例如EOT 将通过 shell 执行字符串。
        猜你喜欢
        • 2013-08-08
        • 2013-05-22
        • 2011-02-09
        • 2010-09-10
        • 2014-01-24
        • 1970-01-01
        • 2019-04-23
        • 1970-01-01
        相关资源
        最近更新 更多