正则表达式匹配不在引号中的关键字

我如何能够查找不在字符串中的kewords。

例如,如果我有文字:

你好,这个文字就是一个例子。

bla bla bla“这个文字在一个字符串里面”

“随机字符串”更多文字bla bla bla“foo”

我希望能够匹配不在" "内的所有text 。 在其他我想匹配:

在此处输入图像描述

注意我不想匹配红色突出显示的文本,因为它在字符串中


可能的方法:

我一直在努力,这是我到目前为止:

(?s)((?")|text)(?(q).*?"|)

请注意,正则表达式使用if语句:(?(谓词)true替换| ​​false替代)

所以正则表达式会读:

找到“或文字。如果你找到”然后继续选择,直到你找到“再次(。*?”),如果你找到文字然后什么也不做……

当我运行该正则表达式时,我匹配整个字符串。 我问这个问题是为了学习。 我知道我可以删除所有字符串然后寻找我需要的东西。

这是一个答案:

 (?<=^([^"]|"[^"]*")*)text 

这意味着:

 (?<= # preceded by... ^ # the start of the string, then ([^"] # either not a quote character |"[^"]*" # or a full string )* # as many times as you want ) text # then the text 

您可以轻松扩展它以处理包含转义的字符串。

在C#代码中:

 Regex.Match("bla bla bla \"this text is inside a string\"", "(?<=^([^\"]|\"[^\"]*\")*)text", RegexOptions.ExplicitCapture); 

从评论讨论中添加 - 扩展版本(基于每行匹配并处理转义)。 使用RegexOptions.Multiline

 (?<=^([^"\r\n]|"([^"\\\r\n]|\\.)*")*)text 

在C#字符串中,这看起来像:

 "(?<=^([^\"\r\n]|\"([^\"\\\\\r\n]|\\\\.)*\")*)text" 

既然您现在想要使用**而不是"这里是一个版本:

 (?<=^([^*\r\n]|\*(?!\*)|\*\*([^*\\\r\n]|\\.|\*(?!\*))*\*\*)*)text 

说明:

 (?<= # preceded by ^ # start of line ( # either [^*\r\n]| # not a star or line break \*(?!\*)| # or a single star (star not followed by another star) \*\* # or 2 stars, followed by... ([^*\\\r\n] # either: not a star or a backslash or a linebreak |\\. # or an escaped char |\*(?!\*) # or a single star )* # as many times as you want \*\* # ended with 2 stars )* # as many times as you want ) text # then the text 

由于此版本不包含"字符,因此使用文字字符串更清晰:

 @"(?<=^([^*\r\n]|\*(?!\*)|\*\*([^*\\\r\n]|\\.|\*(?!\*))*\*\*)*)text" 

这可能会变得非常棘手,但是这里有一种可能的方法可以确保匹配文本和字符串结尾之间有偶数个引号:

 text(?=[^"]*(?:"[^"]*"[^"]*)*$) 

text替换为要匹配的正则表达式。

Rubular: http ://www.rubular.com/r/cut5SeWxyK

说明:

 text # match the literal characters 'text' (?= # start lookahead [^"]* # match any number of non-quote characters (?: # start non-capturing group, repeated zero or more times "[^"]*" # one quoted portion of text [^"]* # any number of non-quote characters )* # end non-capturing group $ # match end of the string ) # end lookahead 

我只是贪婪地匹配非捕获组中引号中的文本来过滤它们,然后使用捕获组来获取非引用的答案,如下所示:

 ".*(?:text).*"|(text) 

您可能希望为字边界等细化一点。但这应该可以让您到达目的地,并且是一个清晰的可读样本。

到目前为止,我已经多次使用这些答案,并希望分享修复此问题的替代方法,因为有时我无法实现和使用给定的答案。

不是将关键字与某些东西匹配,而是将任务分解为两个子任务:

  1. 替换您不需要与空字符串匹配的所有内容
  2. 使用普通比赛

例如,要替换我使用的引号中的文本:

 [dbo].[fn_Utils_RegexReplace] ([TSQLRepresentation_WHERE], '''.*?(? 

或者更清楚: '.*?(?

我知道这可能看起来像双重工作并且对某些平台/语言有性能影响,所以每个人都需要测试它。