0

我有以下作为我的输入,

输入

Random Line 1
Random Line 2
From: person1@example.com
Date: 01-01-2011
To: friend@example.com
   Subject: One
Random Line 3
Random Line 4
From: person2@example.com
   Subject: Two
Random Line 5
From: person3@example.com
   Subject: Three
This is the end

以下是我预期的匹配文本,

预期产出

From: person2@example.com
   Subject: Two

注意:From: person2@example.comSubject: Two之间可能有零行或多行

我尝试使用正则表达式,

/(From.*?Subject:\s*Two)/m

上面的正则表达式匹配第一个From。谁能帮我匹配预期的输出?提前致谢。

4

4 回答 4

3

在您的正则表达式之前添加.*以仅获得预期的两行。

.*(From.*?Subject:\s*Two)

由于贪心量词*,正则表达式引擎匹配到最后一个From字符串(即,包含该字符串的行之前的那个Two)。然后从字符串From到字符串Two被捕获到一个组中(使用非贪婪量词。所以它做一个最短匹配)。

演示

于 2014-07-08T08:21:58.433 回答
2

这是另一种方式:

代码

text.scan(/.*(From:.*?\n).*(Subject: Two)/m).join

例子

text = <<_
Line 1
From: person1@example.com
To: friend@example.com
   Subject: One
Line 5
From: person2@example.com
Line 7
   Subject: Two
Line 9
From: person3@example.com
   Subject: Three
The End
_

text.scan(/.*(From:.*?\n).*(Subject: Two)/m).join
  #=> "From: person2@example.com\nSubject: Two"

解释

正则表达式

r = /.*(From:.*?\n).*(Subject: Two)/m

跳过所有字符,直到到达string之后(在一些不匹配字符之后)的最后一个字符串。具体来说:"From:...\n""Subject Two"

  • .*是贪婪的,它会消耗尽可能多的字符,包括"From:...\n"与正则表达式不匹配的行,直到第一个捕获组的开头。
  • (From:.*?\n)是第一个捕获组,捕获"From:到该行的末尾。?in.*?使.*非贪婪,因此它在\n它到达的第一个停止。
  • .*消耗所有后续字符,直到到达第二个捕获组。
  • (Subject: Two)是第二个捕获组。
于 2014-07-08T19:04:32.530 回答
2

确保第一行和第二行之间只有一个换行符:

/(From[^\n]*\n\s*Subject:\s*Two)/m

看这里

另外,我相信删除会使/m它更容易:

/(From.*?\s*Subject:\s*Two)/

看这里

如果中间可能有线条,则需要使用负前瞻

/(From[^\n]*\n(^(?!From)[^\n]*\s*)*Subject:\s*Two)/m

看这里

此正则表达式执行以下操作:

  1. From[^\n]*\n- 匹配从From行尾开始的文本
  2. (^(?!From)[^\n]*\s*)*- 匹配零个或多个不以 From 开头的行(负前瞻
  3. Subject:\s*Two- 匹配包含Subject:[空格]的文本Two
于 2014-07-08T08:23:45.417 回答
1

用这个:

if subject =~ /^From[^\r\n]*\s*\S*Subject: Two/
    match = $&
else
    match = ""
end

解释

  • ^锚断言我们在一行的开头
  • From匹配文字字符
  • [^\r\n]*匹配任何不是换行符的字符
  • \s*匹配任何空格,包括换行符
  • \S*匹配任何非空白字符
  • Subject: Two匹配文字字符

多行版本

作为对您的评论和新注释的回应,这里是另一个版本,它允许在From和之间使用多行Two

if subject =~ /^From(?:(?:(?!^From).)*+\s*+)*\S*Subject: Two/
    match = $&
else
    match = ""
end
于 2014-07-08T09:30:29.127 回答