在使用qq对变量声明使用匹配运算符时,为什么括号可以解决声明本身?

时间:2016-11-29 17:02:36

标签: perl

我知道标题是满口的,但我不知道如何使它更简洁。

在Perl中阅读多行字符串我在PerlMaven about here-documents发现了这篇文章。它讨论了here- documents qqq。在所有情况下,保留前导空格,如用于代码缩进的空格。我明白那个。在示例节目中减轻这种情况的方法是使用正则表达式替换来删除前导空格。

if ($send) {
    (my $message = qq{
        Dear $name,

        this is a message I plan to send to you.

        regards
          the Perl Maven
        }) =~ s/^ {8}//mg;
    print $message;
}

当我试图采用这种风格时,我就这样写了(不小心):

if ($send) {
    my $message = (qq{
        Dear $name,
          words and stuff
        }) =~ s/^ {8}//mg;
    print $message;
}

Perl对我来说不是一种强硬的语言。我上面尝试的不正确的语法对我来说似乎很自然。由于我错误地使用匹配运算符,我显然得到错误:

  

无法在nagios_send_html_service_mail.pl第91行修改字符串替换(s ///),靠近“s / ^ {8} // mg;”

在工作示例中为什么 $message实际包含更改?当你声明变量时我似乎被允许做的事情,但我只是想知道它被称为什么。

2 个答案:

答案 0 :(得分:6)

因为这是关于你想要改变的东西。

=~是绑定运算符,它告诉您应用模式匹配的内容。

my $message = "fish";
   $message =~ s/i/a/; 
print $message

会工作,因为你正试图改变$message。这就是第一个例子中发生的事情 - 消息被设置为 first ,然后由于括号而应用了修改。

但是,=~=的绑定更紧密。它首先发生。

此优先权记录在perldoc perlop

所以在第一个例子中 - 由于括号,然后转换,首先发生赋值。没有括号,它首先尝试变换:

"fish" =~ s/i/a/;

哪个是无效的,因为它不是在那个时候改变一个变量,而是一个静态的文本。

my $result = "fish" =~ s/i/a/; #gives same error.
( my $result = "fish" ) =~ s/i/a/; #works.

您可以使用r正则表达式修饰符以另一种方式执行此操作(如果您的perl版本足够新),则返回值:

my $result = "fish" =~ s/i/a/r;

r标志停止尝试修改该值,只是“返回”操作的结果,然后可以将其分配给$result

答案 1 :(得分:5)

=~的优先级高于=,因此

my $message = (qq{...}) =~ s/^ {8}//mg;

相当于

my $message = ( (qq{...}) =~ s/^ {8}//mg );

这会尝试修改qq返回的常量,这是不允许的。

标量上下文中的标量赋值运算符返回其左侧(作为左值) [1] 。这意味着

( $message = qq{...} ) =~ s/^ {8}//mg;

相当于

$message = qq{...};
$message =~ s/^ {8}//mg;

此外,my $message会返回$message(作为左值),所以

( my $message = qq{...} ) =~ s/^ {8}//mg;

相当于

my $message;
$message = qq{...};
$message =~ s/^ {8}//mg;

这就是原始解决方案有效的原因。

请注意,缩进更改会破坏您的代码,因此您的技术很脆弱。请考虑使用以下内容:

if ($send) {
    (my $message = qq{
        !Dear $name,
        !
        !this is a message I plan to send to you.
        !
        !regards
        !  the Perl Maven
    }) =~ s/^[^\S\n]+[!\n]?//mg;
    print $message;
}

以上也删除了不需要的空白引导线。

最后,请注意5.14中引入的r修饰符。

if ($send) {
    my $message = qq{
        !Dear $name,
        !
        !this is a message I plan to send to you.
        !
        !regards
        !  the Perl Maven
    } =~ s/^[^\S\n]+[!\n]?//mgr;
    print $message;
}
  1. 有关赋值运算符返回的详细信息,请参阅Mini-Tutorial: Scalar vs List Assignment Operator