6

我正在处理 Request Tracker 4.0 中的一些 Perl 代码,并且遇到了票证请求者的消息被切断的错误。我是 Perl 的新手,我已经使用正则表达式做了一些工作,但是即使在阅读了很多内容之后,我也遇到了一些麻烦。

我已将问题缩小到这行代码:

$content =~ s/\n-- \n.*?$//s

我不完全理解它在做什么,并希望得到更好的解释。

我知道这s/ /是匹配模式\n-- \n.*?$并将其替换为空。

我不明白是做什么.*?$的。以下是我的基本理解:

  • .是除 \n 之外的任何字符
  • *是前一个字符的 0 次或多次
  • ?是前一个字符的 0 或 1 倍
  • $是字符串的结尾

然后,据我了解,决赛s使.比赛新线

因此,粗略地说,我们将替换任何以 - 开头的文本\n-- \n- 这行代码导致了一些可疑的行为,如果有人可以解释这里发生了什么,我很乐意解决这些问题。

有人可以解释这条线在做什么吗?它只是在第一个文本之后删除所有文本 \n-- \n还是还有更多内容?

冗长的部分/现实生活中的问题(您无需阅读此内容即可回答问题)

我的确切问题是它正在削减签名处的引用内容。

因此,如果来自客户的电子邮件 A 说:

订单 ABCD 是怎么回事?
-- 一些客户

工作人员回复说(注意丢失客户签名)

今天发货

订单 ABCD 是怎么回事?

客户回复

没收到,没发货!!!
-- 一些客户

今天发货

订单 ABCD 是怎么回事?

当我们回复时,他们的信息将截断——这会扼杀所有上下文。

它今天发货,跟踪号 12345

没收到,没发货!!!

并导致更多的工作来解释它是什么顺序等。

4

3 回答 3

8

你几乎是正确的:它删除了从最后一次出现的 "\n-- \n" 到最后的所有内容。这并没有从第一次出现中删除所有内容,这是由于非贪婪运算符- 它告诉正则表达式引擎匹配前面模式 ( )?的最短后置形式。.*

这是做什么的:在电子邮件通信中,签名通常完全通过这种模式与消息正文分开:一行正好由两个破折号和一个尾随空格组成。因此,正则表达式所做的就是删除从签名分隔符开始到最后的所有内容。

现在您的客户所做的(手动或他的电子邮件客户端)是在签名分隔符后添加引用的电子邮件回复。这是非常不寻常的:引用的回复必须位于签名修饰符之前。我不知道有一个电子邮件客户端是故意这样做的,但是可惜有很多程序只是从中获取电子邮件(从引用的字符集问题到 SMTP 不合格,您可能会犯大量错误) ,所以当得知确实有这样的客户时,我不会感到惊讶。

另一种可能是,这是客户的一种做作——就像签了自己的名字一样--。但是,我怀疑这不是手动完成的,因为人类很少在两个破折号后插入一个尾随空格,然后是一个换行符。

于 2013-08-07T20:01:15.900 回答
2

?跟随一个量词(?、或)时*,它会修改该量词[1]的贪心程度。通常,这些量词尽可能匹配最多的字符,但对于,它们匹配的最少。+{m,n}?

say "Greedy:     ", "abc1234" =~ /\w(.*)\d/;
say "Non-greedy: ", "abc1234" =~ /\w(.*?)\d/;

输出:

bc123
bc

由于有两个位置$可以匹配(在尾随换行符之前或字符串末尾),因此具有以下效果:

$_ = "abc\n-- \ndef\n";
say "Greedy:     <<" . s/\n-- \n.*$//sr  . ">>";
say "Non-greedy: <<" . s/\n-- \n.*?$//sr . ">>";

输出:

Greedy:     <<abc>>
Non-greedy: <<abc
>>

它确保不会删除终止最后一行的换行符。以下是更直接的等价物:

s/\n-- \n.*/\n/s

s/(?<=\n)-- \n.*//s   # Slow

s/\n\K-- \n.*//s      # Requires 5.10

请注意,它将从第一个--.

$ perl -E'say "abc\n-- \ndef\n-- \nghi\n" =~ s/\n-- \n.*?$//sr'
abc

如果你想从最后一个开始删除,你必须.*用保证不匹配的东西替换--

$ perl -E'say "abc\n-- \ndef\n-- \nghi\n" =~ s/\n-- \n(?:(?!-- \n).)*?$//sr'
abc
-- 
def

笔记:

  1. 如果它跟随另一个量词修饰符(例如/.*+?/),它也具有相同的含义。
于 2013-08-07T20:54:25.773 回答
1

有一个不错的 CPAN 模块,可以帮助你以后理解正则表达式:YAPE::Regex::Explain

你可以在这里找到它的在线版本:http ://rick.measham.id.au/paste/explain.pl

通过网站运行您的正则表达式会返回以下内容:

NODE                     EXPLANATION
--------------------------------------------------------------------------------
  \n                       '\n' (newline)
--------------------------------------------------------------------------------
  --                       '-- '
--------------------------------------------------------------------------------
  \n                       '\n' (newline)
--------------------------------------------------------------------------------
  .*?                      any character except \n (0 or more times
                           (matching the least amount possible))
--------------------------------------------------------------------------------
  $                        before an optional \n, and the end of the
                           string

根据文档,“不支持在 Perl 版本 5.6 之后添加的正则表达式语法,特别是在 5.10 中添加的任何构造”,但实际上您仍然应该能够使用它来帮助理解您遇到的大多数正则表达式。

于 2013-08-07T21:25:53.890 回答