【问题标题】:What's the difference between these two Perl snippets?这两个 Perl 片段有什么区别?
【发布时间】:2011-04-30 06:45:26
【问题描述】:
print <<EOF
stuff
EOF
;


print <<EOF;
stuff
EOF

你为什么要使用一个而不是另一个?

【问题讨论】:

  • 我喜欢第一个,因为它对 emacs 缩进引擎有点友好。
  • 我认为这是一个足够诚实的问题,而不是主观/争论。
  • 一如既往,TIMTOWTDI :-) .
  • @Zaid:确实。我不是 Perl 程序员,甚至可能对 heredocs 不太熟悉的人。这两个 sn-ps 做的事情并不明显。

标签: perl heredoc


【解决方案1】:

Randal Schwartz这里有一篇很棒的文章,文档HERE

关于这里文档有几点需要记住:

  1. Perl 中的; 是语句终止符,并且是所有 Perl 语句(有一些例外)包括here 文档字符串所必需的;
  2. here 文档看起来很有趣,实际上只是一个大字符串;
  3. here 文档必须有一个终止 CR(与大多数其他 Perl 语句不同);
  4. 您可以在开始标记之后或结束标记之后添加任意 Perl 代码。如果在结束标记之后,它必须在单独的行上。无论哪种情况,代码都会对 here 字符串的文本进行操作;
  5. 标签上使用的引号会影响字符串。双引号就像 Perl 中的双引号字符串,单引号不插入,反引号被传递给 shell。无引号等价于双引号;
  6. TIMTOWTDI,但有些表格很难阅读;
  7. 引用perldoc -q "HERE documents"(和perlfaq4):

[&lt;&lt; 部分] 的末尾(可能)应该有一个分号。

你不能(轻易地)在标签前面有任何空格。

您拥有的两种形式在功能上是等效的。正如{ ... } if (blah blah)if (blah blah) { ... } 一样。虽然这两个语句在功能上是等效的,但它们的“读法”不同。

每一个都是等效且有效的 Perl here 文档:

my %data = <<END
fred: Fred Flintstone
barney: Barney Rubble
betty: Betty Rubble
wilma: Wilma Flintstone
END
 =~ /(\w+): (.*)/g;

my %data = <<END =~ /(\w+): (.*)/g;
fred: Fred Flintstone
barney: Barney Rubble
betty: Betty Rubble
wilma: Wilma Flintstone
END

# You must have a CR after the "END". Can't be EOF...

两者都将 Flintstones 的 %data 哈希设置为 first=&gt;"full name"。您更愿意在代码中看到哪个?

注意第二种形式有一个陷阱:终止标记后需要有文本或空格,否则您可能会得到Can't find string terminator "END" anywhere before EOF。我认为这就是为什么您会在某些人的 here 文档中看到孤独的 ;

恕我直言,; 属于 here doc 标记的第一个实例或其后面的代码之后。如果它在结束标记之后,则更难阅读。 除非结束标签的形式类似于语句修饰符或警告或die逻辑。这只是我的个人风格指南。

【讨论】:

    【解决方案2】:

    作为tchrist points out,大多数人忽略的一件事是heredoc 运算符在终止代码之后采用任意Perl 代码

    这意味着您可以(可以说)进行更自然的操作,例如:

    my $obj = Foo::Bar->new(content => <<EOP)->do_stuff->sprint();
        This is my content
        It's from a heredoc.
    EOP
    

    一个结果是,您也可以将它们堆叠更多(在我看来;)比“未堆叠”更易读:

    -- stacked_heredoc.pl
    #!/usr/bin/perl
    use strict;
    use warnings;
    
    print join(<<JOINER, split("\n", <<SOURCE));
    
    ------------------------------
    JOINER
    This is my text
    this is my other text
    a third line will get divided!
    SOURCE
    

    诗句未堆叠的heredoc ...

    -- unstacked_heredoc.pl
    #!/usr/bin/perl
    use strict;
    use warnings;
    
    my $joiner = <<JOINER
    
    ------------------------------
    JOINER
    ;
    
    my $source = <<SOURCE
    This is my text
    this is my other text
    a third line will get divided!
    SOURCE
    ;
    
    print join($joiner, split("\n", $source));
    

    【讨论】:

      【解决方案3】:

      您应该像对待字符串文字一样对待heredoc 标记。不要将更多的标点或语法延迟到其内容之后。这是误导和容易出错的。这里有十个例子都取自真实代码:

      1. ($is_a_valid_rfc_822_addr = &lt;&lt;'EOSCARY') =~ s/\n//g;
      2. $eval = (($Preamble=&lt;&lt;'END1') . $userstuff . &lt;&lt;'END2');
      3. for my $line (&lt;&lt;"End_of_Property_List" =~ m{ \S .* \S }gx) {
      4. $cases .= &lt;&lt;"EDQ" if $timeout;
      5. ($is_a_valid_rfc_822_addr = &lt;&lt;'EOSCARY') =~ s/\n//g;
      6. eval (($Preamble=&lt;&lt;'END1') . $_[0] . &lt;&lt;'END2');
      7. @changes = split("\n", &lt;&lt;"EOCHANGES");
      8. $change .= sprintf(&lt;&lt;"EOP", $in, $out, $in, $out);
      9. eval "{ package $package; " . &lt;&lt;'EOF' . "}";
      10. push @args, dequeue('|Q|', &lt;&lt;'END_OF_ASTRAL_MATCH') if $Opt{astral};

      看看它是如何工作的?

      【讨论】:

        【解决方案4】:

        FWIW,Perl 最佳实践 建议:

        print <<'EOF';
        stuff
        EOF
        

        【讨论】:

        • 不是一回事。单引号抑制插值。该问题的等价物是双引号。
        • @igelkott: 并且 pbp 建议在实际上没有任何插值的情况下使用单引号 :)
        • 不过,OP 中没有发生插值。
        • 也许更新/扩展您的答案? (但没有“编辑:”、“更新:”或类似的 - 答案应该看起来好像是今天写的。)
        【解决方案5】:

        这两个示例在行为上等同于同一件事,但请考虑在打印该块后是否想做其他事情:

        print <<EOF
        stuff
        EOF
        . "more text here";
        

        ...或者您可能需要测试操作的结果:

        print $unstable_filehandle <<EOF
        stuff
        EOF
        or warn "That filehandle finally disappeared: $!";
        

        这些示例是人为设计的,但您可以看到有时灵活地处理文本块之后的代码是多么有用。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2021-01-06
          • 2021-12-17
          • 1970-01-01
          • 2013-03-29
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多