19

我将如何查找不在字符串中的关键字。

例如,如果我有文字:

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

bla bla bla "此文本在字符串中"

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

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

在此处输入图像描述

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


可能的解决方案:

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

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

请注意,正则表达式将 if 语句用作: (?(predicate) true Alternative|false Alternative)

所以正则表达式将显示:

找到 " 或文本。如果找到 " 然后继续选择直到再次找到 " (.*?") 如果找到文本则什么也不做...

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

4

4 回答 4

25

这是一个答案:

(?<=^([^"]|"[^"]*")*)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"
于 2012-07-23T21:01:37.293 回答
7

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

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
于 2012-07-23T20:56:50.257 回答
1

我会简单地在非捕获组中贪婪地匹配文本的引号以将它们过滤掉,然后使用捕获组作为非引用的答案,如下所示:

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

您可能希望针对单词边界等进行一些改进。但这应该可以让您到达您想去的地方,并且是一个清晰易读的示例。

于 2012-07-23T21:04:57.010 回答
0

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

与其匹配关键字,不如将任务分解为两个子任务:

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

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

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

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

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

于 2018-07-30T10:51:56.443 回答