RegEx环视找到Start> Foo,其中Foo bar从未出现过

时间:2014-09-17 00:29:59

标签: regex unix

我为可怕的话题名称道歉,但我想不出进一步抽象这个问题的方法。我一直在试图弄清楚这个问题的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'

谢谢!

2 个答案:

答案 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
 )    
)