C#Regex在自定义标签内匹配NOT

时间:2017-12-30 14:31:22

标签: c# regex

我以

的形式使用标签
[[MyTag]]Some Text[[/MyTag]]

要在整个文本中找到这些标签,我使用以下表达式(这与此问题无关,但对于信息):

\[\[(?<key>.*\w)]\](?<keyvalue>.*?)\[\[/\1\]\]

现在我想匹配并替换不在这些自定义标签内的文本(MYSEARCHTEXT)。

示例:

[[Tag1]]Here I don't want to replace MYSEARCHTEXT[[/Tag1]]
But here MYSEARCHTEXT (1) should be replaced. And here MYSEARCHTEXT (2) needs to be replaced too.
[[AnotherTag]]Here I don't want to replace MYSEARCHTEXT[[/AnotherTag]]
And here I need to replace MYSEARCHTEXT (3) also.

MYSEARCHTEXT是一个单词或短语,在此示例中需要找到3次。

4 个答案:

答案 0 :(得分:0)

我有一个想法可以简化这个。使用以下正则表达式匹配标记文本:

\[.+?\][^\[\]]*?MYSEARCHTEXT[^\[\]]*?\[.+?\]\]

然后替换字符串中的MYSEARCHTEXT,保留捕获的组。

答案 1 :(得分:0)

也许这可行吗?如果我正确理解了问题,那么这将匹配您的代码之外的 MYSEARCHTEXT ,您的匹配将在群组中。这使用positive lookahead

https://regex101.com/r/C8Kuiz/2

(?:\[\[Tag1.*?\/Tag1\]\])\n?(?:.*)(?=(MYSEARCHTEXT))

答案 2 :(得分:0)

您可以使用以下使用您的模式版本的解决方案,并在Regex.Replace方法中添加替代方案,其中匹配评估程序用作替换参数:

var pat = @"(?s)(\[\[(\w+)]].*?\[\[/\2]])|MYSEARCHTEXT";
var s = "[[Tag1]]Here I don't want to replace MYSEARCHTEXT[[/Tag1]]\nBut here MYSEARCHTEXT (1) should be replaced. And here MYSEARCHTEXT (2) needs to be replaced too.\n[[AnotherTag]]Here I don't want to replace MYSEARCHTEXT[[/AnotherTag]]\nAnd here I need to replace MYSEARCHTEXT (3) also.";
var res = Regex.Replace(s, pat, m =>
            m.Groups[1].Success ? m.Groups[1].Value : "NEW_VALUE");
Console.WriteLine(res);

请参阅C# demo

结果:

[[Tag1]]Here I don't want to replace MYSEARCHTEXT[[/Tag1]]
But here NEW_VALUE (1) should be replaced. And here NEW_VALUE (2) needs to be replaced too.
[[AnotherTag]]Here I don't want to replace MYSEARCHTEXT[[/AnotherTag]]
And here I need to replace NEW_VALUE (3) also.

模式详情

  • (?s) - 一个RegexOptions.Singleline内联修饰符选项(.现在匹配任何字符)
  • (\[\[(\w+)]].*?\[\[/\2]]) - 第1组:
    • \[\[ - [[子字符串
    • (\w+) - 第2组:一个或多个单词字符
    • ]] - ]]子字符串
    • .*? - 任意0个字符,尽可能少
    • \[\[/ - [[/子字符串
    • \2 - 与第2组相同的文字
    • ]] - 文字]]子字符串
  • | - 或
  • MYSEARCHTEXT - 要替换​​的某种模式。

当第1组匹配(m.Groups[1].Success ?)时,此值将被放回,否则NEW_VALUE将插入到结果字符串中。

答案 3 :(得分:0)

最好的方法是将两者分别匹配为匹配 然后决定要替换哪个以及根据哪个回写哪个 匹配。 (有人已发布此解决方案,因此我不会复制它)

另一种方法是完全放弃,并对文本进行限定 以 searchtext 之后的前瞻形式。

这显示了如何这样做。

var pat = @"(?s)MYSEARCHTEXT(?=(?:(?!\[\[/?\w+\]\]).)*?(?:\[\[\w+\]\]|$))";
var res = Regex.Replace(s, pat, "NEW_VALUE");

演示:https://ideone.com/KOtNik

格式化:

 (?s)                          # Dot-all modifier
 MYSEARCHTEXT
 (?=                           # Qualify the text with an assertion
      (?:                           # Get non-tag characters
           (?! \[\[ /? \w+ \]\] )        
           . 
      )*?
      (?:                           # Up to -
           \[\[ \w+ \]\]                 # An open tag
        |  $                             # or, end of string
      )
 )