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

时间:2012-07-23 20:45:30

标签: c# regex parsing

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

例如,如果我有文字:

  

您好,本文就是一个例子。

     

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

     

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

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

enter image description here

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


可能的解决方案:

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

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

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

所以正则表达式会读:

  

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

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

4 个答案:

答案 0 :(得分:21)

这是一个答案:

(?<=^([^"]|"[^"]*")*)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"

答案 1 :(得分:6)

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

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

答案 2 :(得分:1)

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

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

你可能想要对字边界等进行一些改进。但这应该可以让你到达你想去的地方,并且是一个清晰的可读样本。

答案 3 :(得分:0)

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

将任务分为两个子任务,而不是从头开始匹配关键字

  1. 将所有不需要匹配的内容替换为空字符串
  2. 使用普通匹配

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

[dbo].[fn_Utils_RegexReplace] ([TSQLRepresentation_WHERE], '''.*?(?<!\\)''', '')

或更清晰:'.*?(?<!\\)'

我知道这可能看起来像是双重工作,并且会对某些平台/语言产生性能影响,所以每个人也都需要对此进行测试。