我有以下作为我的输入,
输入
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
以上正则表达式匹配来自第一个发件人。任何人都可以帮助我匹配预期的输出吗?提前谢谢。
答案 0 :(得分:3)
在正则表达式之前添加.*
以仅获得预期的两行。
.*(From.*?Subject:\s*Two)
由于贪心量词*
,正则表达式引擎匹配最后一个From
字符串(即包含字符串Two
的行之前的字符串)。然后从字符串From
到字符串Two
被捕获到一个组中(使用非贪婪量词。所以它进行最短匹配)。
答案 1 :(得分:2)
确保第一行和第二行之间只有一个换行符:
/(From[^\n]*\n\s*Subject:\s*Two)/m
另外,我相信删除 /m
会让它变得更加容易:
/(From.*?\s*Subject:\s*Two)/
如果您可能在中间有行,则需要使用negative lookahead:
/(From[^\n]*\n(^(?!From)[^\n]*\s*)*Subject:\s*Two)/m
此正则表达式执行以下操作:
From[^\n]*\n
- 匹配以From
开头直至行尾的文字(^(?!From)[^\n]*\s*)*
- 匹配零行或多行不以From 开头(negative lookahead)Subject:\s*Two
- 匹配包含Subject:
[空格] Two
答案 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)
会消耗所有后续字符,直到它到达第二个捕获组。答案 3 :(得分: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