避免意外匹配

时间:2016-04-17 10:12:39

标签: regex

我有一个看起来像这样的字符串:

<text>bla bla BLU bla bla</text>
<text>bla bla bla bla bla</text>
<text>bla BLU bla bla bla</text>
<text>bla ble bla bla bla</text>

我正在寻找一种方法来获取每个<text>条目,其中包含BLU。我尝试使用这个正则表达式:

/<text>[\s\S]*?BLU[\s\S]*?<\/text>/g

我按预期获得2场比赛,但第二场比赛将是:

<text>bla bla bla bla bla</text>
<text>bla BLU bla bla bla</text>

如何避免这种匹配,只能将此结果作为第二场比赛:

<text>bla BLU bla bla bla</text>

1 个答案:

答案 0 :(得分:1)

你的逻辑中有一层。

发生这种情况的原因是因为即使[\s\S]*是懒惰的,它也会一直持续到BLU为止。这意味着它会找到开始<text>标记,然后继续结束,直到找到BLU,直到找到<text>(?:(?!<\/text>)[\s\S])*?BLU[\s\S]*?<\/text>

您可以尝试以下RegEx:

[\s\S]*?

我更改的位是(?:(?!<\/text>)[\s\S])*?[\s\S]

</text>包含在非捕获组中。在小组开始时,如果找到结束[\s\S]*?,则会有否定前瞻失败。

这样</text>永远不会与结束<text>匹配,因此它可以解决您的问题。

Live Demo on Regex101

Demo

请注意,如果开始和结束<text>.*?BLU.*?<\/text> 标记之间没有换行符,则可以使用以下RegEx:

SELECT TOP 1 * FROM 
myTable
ORDER BY CASE WHEN num = '***' THEN 1 ELSE 0 END    
WHERE f1 = something
AND f2 = something
AND f3 = something

Live Demo on Regex101