REGEX:匹配包含短语的文本,它包含在两个单词之间

时间:2015-12-01 20:11:39

标签: regex


我必须匹配包含一些短语的文本,它必须包含在两个常量之间。让我举一个例子:
我的上限和下限是相同的,例如“开始”。现在有更多的文本块被“START”限制。我想在限制之间捕获文本,但捕获的文本必须包含一些短语。

START
text1 text1 text1 phrase1 text text
START
text2 text2 phrase2 text2
START
text3 phrase1
START

现在我想用phrase1捕获文本。它是“text1 text1 text1 phrase1 text text”和“text3 phrase1”。

匹配的文字可能包含START字词。

我的尝试(无法以正确的方式运作)是:START((.|\s)*?phrase1(.|\s)*?)START

START text1 text1 text1 phrase1 text text START被捕获时,我将其保存到变量中,并使用替换正则表达式方法和“START”,所以在它之后它看起来像这样:

START
text2 text2 phrase2 text2
START
text3 phrase1
START

第二次循环后我得到了:

START
text2 text2 phrase2 text2
START

当我得到第三个循环(如果它工作正则表达式应该返回false)但我崩溃了。在一些在线正则表达式中,它显示没有匹配,因此它与模式有关。

编辑:添加循环的代码

set regEx = new RegEx
//sInputString is my text

regEx.pattern = "START((.|\s)*?phrase1(.|\s)*?)START"
set matches = regEx.Execute(sInputString)

do while (matches.count <> 0)
    sInputString = regEx.Replace(sInputString, "START")
    set matches = regEx.Execute(sInputString) //this line crashes after "ending loop"
    //saving to array
loop

1 个答案:

答案 0 :(得分:2)

(.|\s)*?构造效率非常低,会给正则表达式用户带来很多痛苦。始终将其替换为.*?(使用单行修饰符),或[\s\S]*?或使用unrol-the-loop'ed正则表达式。

在你的情况下,你可以像这样使用unroll-the-loop正则表达式:

\bSTART\b([^S]*(?:S(?!TART\b)[^S]*)*)

匹配:

  • \bSTART\b - 整个单词START(如果您不使用整个单词,可以省略\b
  • ([^S]*(?:S(?!TART\b))*) - 一个匹配的捕获组
    • [^S]* - 除S
    • 以外的0个或多个字符
    • (?:S(?!TART\b)[^S]*)* - 0个或更多个序列...
      • S(?!TART\b) - S未跟随TART和字边界
      • [^S]* - 除S
      • 以外的0个或多个字符

获得

text1 text1 text1 phrase1 text text
text2 text2 phrase2 text2
text3 phrase1

请参阅regex demo

现在,如果您只需要2个子字符串,只需在结尾处添加\bSTART\b,它将使用尾随START

\bSTART\b([^S]*(?:S(?!TART\b)[^S]*)*)\bSTART\b

请参阅another demo(捕获text1 text1 text1 phrase1 text texttext3 phrase1)。

第二个正则表达式基本上与(?s)\bSTART\b(.*?)\bSTART\b相同,但是对于较长的文本来说效率要高得多,但是.*?懒惰点匹配(匹配0个或更多任何字符但是当子串很短时,最好尽可能少地返回有效匹配

最后一点:如果您不需要匹配整个单词,则不必使用单词边界\b