这两个Perl片段有什么区别?

时间:2010-10-25 15:14:46

标签: perl heredoc

print <<EOF
stuff
EOF
;


print <<EOF;
stuff
EOF

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

5 个答案:

答案 0 :(得分:14)

这两个例子在行为上是相同的,但考虑一下你是否想在打印该块之后再做其他事情:

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

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

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

这些例子都是人为设计的,但你可以看一下,如果能够灵活地了解文本块后面的代码是多么有用。

答案 1 :(得分:9)

正如tchrist指出的那样,大多数人忽略的一件事是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));

答案 2 :(得分:4)

你应该将heredoc令牌与它们所在的字符串文字完全一样。在内容之后,不要延迟进一步的标点符号或语法。这是误导和容易出错的。以下是从实际代码中获取的十个示例:

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

答案 3 :(得分:2)

FWIW, Perl最佳实践建议:

print <<'EOF';
stuff
EOF

答案 4 :(得分:1)

Randal Schwartz在这里有一篇很好的文章HERE

这里有几件事需要记住:

  1. Perl中的;是语句终止符,是所有Perl语句(有一些例外)所必需的,包括此处的文档字符串;
  2. 这里的文件是一个有趣的陈述,实际上只是一个大字符串;
  3. 此处的文档必须有终止CR(与大多数其他Perl语句不同);
  4. 您可以在开始标记之后或结束标记之后立即使用任意Perl代码。如果在结束标记之后,它必须在单独的行上。在任何一种情况下,代码都在这里的字符串文本上运行;
  5. 您在代码上使用的引号会影响字符串。双引号就像Perl中的双引号字符串,单引号不插入,后引号传递给shell。没有引号等同于双引号;
  6. TIMTOWTDI,但有些表格难以阅读;
  7. 引自perldoc -q "HERE documents"(和perlfaq4):

    &lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;一部分。

    [可能]应该是<<部分结尾处的分号。

    您不能(轻松)在代码前面留出任何空间。

  8. 您拥有的两种形式在功能上是等同的。正如{ ... } if (blah blah)if (blah blah) { ... }相同。虽然这两个陈述在功能上是等同的,但它们“阅读”的方式不同。

    这些文件中的每一个都是等效且有效的Perl文件:

    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=>"full name"。您希望在代码中看到哪些内容?

    注意第二种形式是有一个问题的形式:在终止标记后需要有文字或空格,或者你可能会Can't find string terminator "END" anywhere before EOF我认为这就是为什么你看到单独的;有些人在这里的文档。

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