13

多年来,我一直断断续续地使用 Perl 进行编程,尽管它只是偶尔作为我的主要语言。因为我经常几个月不写任何 perl,我非常依赖我的折耳骆驼书来提醒我如何做事。然而,当我一字不差地复制食谱时,这让我很困扰。这是最令人烦恼的问题之一:在第 3 版 Camel 的第 154 页上,有一个“modifying strings en passant ”的示例,内容如下:

($lotr = $hobbit) =~ s/Bilbo/Frodo/g;

Q1)这里发生了什么?正则表达式到底是在什么基础上运行的?

Q2) 对于“从 $a 中获取字符串,使用正则表达式对其进行修改,将结果放入 $b”这样的基本操作,这种近乎神奇的语法是否必要?

Q3) 如何使用循环默认变量作为初始字符串来执行此操作?

提前向 Perl 的梦想家们道歉,对于他们来说,上面的内容看起来非常自然。

4

3 回答 3

22

嗯……($lotr=$hobbit) =~ s/Bilbo/Frodo/g是 Perl 的众多魔法之一。现在寻求一些答案。

Q1)$lotr被分配了包含在 中的值$hobbit。赋值后,我们可以忘记源变量。将其视为($lotr = $hobbit)自己的声明,就好像我们写过:

$lotr = $hobbit;
$lotr =~ s/Bilbo/Frodo/g;

反而。正则表达式正在运行$lotr

Q2)语法只是上面给出的片段的单行版本。将其视为“从 复制字符串$a,将其复制到$b,并$b使用正则表达式进行修改”,而不是“从 获取字符串$a,使用正则表达式对其进行修改,将结果放入$b

Q3)我假设您的意思是“循环默认变量”的默认模式搜索空间?在这种情况下,只需使用$_而不是$hobbit

while (<>) {
  chomp;
  ($lotr = $_) =~ s/Bilbo/Frodo/g;
  print "\$lotr = [$lotr]\n";
  print "\$_    = [$_]\n";
}

有趣的$_是,这个操作并没有修改魔法变量。这就是您可以得出的结论,即赋值发生正则表达式替换之前,并且替换不会以任何方式在默认模式空间上进行交互。

对于有经验的 Perl 程序员来说……我不知道有多少人会被 Perl 语法所迷惑,不管他们盯着它看了多久,当然除了 Schwartz 先生 ;)

于 2008-12-07T02:11:01.453 回答
5

不同的语言对赋值运算符做不同的事情。在某些情况下,它是一个语句,而不是一个表达式,因此不能组合成一个更大的表达式。在某些情况下,它返回分配的值,但仅作为值(通常称为右值),而不是本身可以修改或分配的东西(左值)。这方面的一个例子是 C,您可以在其中编写:

 a = b = c;  # assign value of c to b and a

但不是:

 ++(b = a);  # assign value of a to b, then increment b

在某些情况下,分配的结果是分配给的左值。(在 Perl 中,这仅适用于标量赋值;列表赋值是一个更复杂的野兽。)所以你可以这样做 ++($b=$a) 或 ($b=$a) =~ s/a/b/ 或任何其他需要左值的操作,它将首先进行分配,然后进一步修改分配给的左值。

于 2008-12-07T02:40:12.830 回答
1

如果在 Q2 中您的意思是从 $a 中获取子字符串,您可能会发现这个习语很有用:

($b) = $a =~ /(substring-to-match)/;
$b =~ s/regex-on-susbtring/result-string/;

还要注意 $a 和 $b 在 Perl 中不是普通变量,因为它们具有与排序函数相关的特殊范围规则。有关详细信息,请参阅“perldoc perlvar”。

于 2008-12-07T03:07:58.423 回答