我必须匹配包含一些短语的文本,它必须包含在两个常量之间。让我举一个例子:
我的上限和下限是相同的,例如“开始”。现在有更多的文本块被“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
答案 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
(?:S(?!TART\b)[^S]*)*
- 0个或更多个序列...
S(?!TART\b)
- S
未跟随TART
和字边界[^S]*
- 除S
获得
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 text
和text3 phrase1
)。
第二个正则表达式基本上与(?s)\bSTART\b(.*?)\bSTART\b
相同,但是对于较长的文本来说效率要高得多,但是.*?
懒惰点匹配(匹配0个或更多任何字符但是当子串很短时,最好尽可能少地返回有效匹配。
最后一点:如果您不需要匹配整个单词,则不必使用单词边界\b
。