我为可怕的话题名称道歉,但我想不出进一步抽象这个问题的方法。我一直在试图弄清楚这个问题的RegEx语法,并倾听有关外观的问题,但无济于事。
我想将开始的结果返回到 foo 的第一个实例(除非后面紧跟 bar )或文件的结尾。此外,如果 foo bar 出现在 foo!bar 或文件结尾之前,我不希望返回任何内容。
以下是我迄今为止一直在使用的内容。我可能完全偏离轨道;但是,我绝对希望留在RegEx内,除非完全不可能。我已经使用非RegEx解决了这个问题,但我正在努力扩展我对RegEx的理解,因为它困扰我,我无法弄清楚如何进行此搜索。我正在使用的RegEx实现是PCRE。
目前,无论 foo bar 是否显示为第一个 foo ,此RegEx都会报告。我觉得好像我错过了一些简单的解决方案,但是使用负面的lookbehind和其他方法,如果 foo bar 显示为第一个 foo <我将无法使搜索返回任何内容/ strong>同时还返回 foo!bar 单独出现的情况, foo bar 之前,或者根本没有出现 foo 的情况。
当前搜索:
start(?:\n|\r|.)*?(?:\Z|foo(?! +bar))
这是三个示例文件以及我希望搜索返回单引号所描述的内容。
示例1:不应该返回任何内容。
Start
Text
Text
Foo Bar
Foo Doo
示例2:应在引号之间返回文字。
'Start
Text
Text
Foo Doo
Foo' Bar
示例3:应在引号之间返回文字。
'Start
Text
Text'
谢谢!
答案 0 :(得分:1)
首先需要在“开始”之后阻止内容中的“foo”。为此,您可以使用多种方法。一种众所周知的方法是使用:(?:(?!foo).)*
(确保您匹配的每个字符不是您不想要的字的开头)。然而,这种方式通常不是非常高效,因为在每个位置都会测试前瞻。
另一种方法是使用您想要避免的单词的第一个字符,并使用它构建负字符类。所以你可以像这样描述内容:
(?>[^f]+|f(?!oo))*
这种方法的优点是限制仅在遇到第一个字母“f”时执行的先行测试的数量。不方便的是,您需要对模式中的字母和单词的其他部分进行硬编码,或者使用单词的子字符串动态构建模式。 (sprintf
在这种情况下可以派上用场)
然后整个模式变成:
start(?>[^f]+|f(?!oo))*(?:foo(?! bar)|\z)
模式说明:
start
(?> # open an atomic group
[^f]+ # all characters except f (one or more times)
| # OR
f(?!oo) # f not followed by oo
)* # repeat the group zero or more times
(?:
foo(?! bar) # "foo" not followed by a space and "bar"
| # OR
\z # end of the string
)
答案 1 :(得分:0)
它有点乱,但我们走了:
((?(?=.*Foo Bar)Start.*?Foo(?= Bar(?![\s]*$)(?!.*?foo (?!bar)))|.*))
注意:您需要启用&#39;修饰符,使点匹配换行符。 输出位于第一个捕获组(\ 1)中。详细解释在底部。
作为一般性评论,代码中的条件(if / esle)可能比在正则表达式中更容易。它也更易读,更易于维护。
顺便说一下,你可以试试这个正则表达式here。
希望它有所帮助! :d
( # first capturing group
(? # if conditional
(?=.*Foo Bar) # if(foo bar exists in this file), using look ahead
Start.*?Foo # Match Start to the first instance of Foo
(?= # Look ahead
Bar # Match space and Bar
(?![\s]*$) # Match !(white spaces and end of line)
(?!.*?foo (?!bar))) # Match !(foo !bar)
| # else
.* # Match everything
)
)