匹配两个单词之间的文字(单词在匹配的文本中不重复)

时间:2014-07-08 08:19:27

标签: ruby regex rubular

我有以下作为我的输入,

输入

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

注意: 发件人:person2@example.com 主题:两个

之间可能有零行或多行

我尝试使用正则表达式

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

以上正则表达式匹配来自第一个发件人。任何人都可以帮助我匹配预期的输出吗?提前谢谢。

4 个答案:

答案 0 :(得分:3)

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

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

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

DEMO

答案 1 :(得分:2)

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

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

see here

另外,我相信删除 /m会让它变得更加容易:

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

see here

如果您可能在中间有行,则需要使用negative lookahead

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

see here

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

  1. From[^\n]*\n - 匹配以From开头直至行尾的文字
  2. (^(?!From)[^\n]*\s*)* - 匹配零行或多行不以From 开头(negative lookahead
  3. Subject:\s*Two - 匹配包含Subject: [空格] Two
  4. 的文字

答案 2 :(得分: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

跳过所有字符,直到它到达 last 字符串"From:...\n",后面跟着(在一些不匹配的字符之后)字符串"Subject Two"。具体做法是:

  • .*,贪婪,消耗尽可能多的字符,包括与正则表达式不匹配的行"From:...\n",直到第一个捕获组的开头。
  • (From:.*?\n)是第一个捕获组,将"From:捕获到该行的末尾。 ? .*? .*使\n非贪婪,因此它会在到达的第一个.*处停止。
  • (Subject: Two)会消耗所有后续字符,直到它到达第二个捕获组。
  • {{1}}是第二个捕获组。

答案 3 :(得分:1)

使用此:

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

<强>解释

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

多行版

在回复您的评论和新笔记时,这是另一个允许FromTwo之间有多行的版本:

if subject =~ /^From(?:(?:(?!^From).)*+\s*+)*\S*Subject: Two/
    match = $&
else
    match = ""
end