【问题标题】:Need a C# regex pattern that includes any character except excluded word需要一个 C# 正则表达式模式,该模式包含除排除单词之外的任何字符
【发布时间】:2019-12-16 09:19:36
【问题描述】:

我正在尝试创建一个以“WORD”开头并匹配除原始“WORD”之外的所有字母、数字和字符的模式,直到“ENDWORD”为止。

在这个例子中,我希望它匹配“WORD”的第二次出现并匹配到“ENDWORD”;但是,它从第一次出现开始,并没有正确排除“WORD”的第二次出现。

看起来好像这个技巧可以匹配除“WORD”之外的任何字符。下面的示例使用了一个否定的前瞻,它被前面的“。”否定。 (任何),但我不确定如何将肯定的“任何”或换行符与否定词结合起来。任何帮助将不胜感激。

这是我在 LinqPad 中运行的示例 c# 程序。

void Main() {

var text =
    @"WORD 
    [asdf] ---
    123/\*&
    WORD
    [asdf] ---
    123/\*&
    ENDWORD
    [asdf] ---
    123/\*&";

var pattern = $"(WORD).|\\n\\b(?!WORD)\\b.|\\n*(ENDWORD)";

Regex rgx = new Regex(pattern);
foreach (Match match in rgx.Matches(text))
{
    match.Dump();
}

}

另一种说明问题的方法是从“ENDWORD”开始(捕获它),回溯,忽略所有字符,直到找到第一次出现的“WORD”并捕获它。刚刚修改以澄清“ENDWORD”不是字符串的结尾。

【问题讨论】:

标签: c# regex


【解决方案1】:

对于您的示例数据,您可以首先匹配WORD,前面有一个空格或制表符。然后重复匹配不包含 WORD 的行,直到遇到包含ENDWORD 且前面有空格或制表符的行。

要检查该行是否不包含 WORD,您可以使用否定前瞻。

[ \t]WORD\b.*(?:\r?\n(?!.*[ \t](?:END)?WORD\b).*)*\r?\n[ \t]+ENDWORD\b

说明

  • [ \t] 匹配空格或制表符
  • WORD\b匹配WORD和单词边界
  • .* 匹配除换行符以外的任何字符 0+ 次
  • (?:非捕获组
    • \r?\n(?!.*[ \t](?:END)?WORD\b) 重复 0+ 次不包含可选 END 后跟 WORD 的行
    • .*如果是这样,则匹配整行
  • )*关闭非捕获组并重复0+次
  • \r?\n[ \t]+ENDWORD\b 匹配换行符、1+ 个空格或制表符以及 ENDWORD 与单词边界

Regex demo | C# demo

例如:

var pattern = @"[ \t]WORD\b.*(?:\r?\n(?!.*[ \t](?:END)?WORD\b).*)*\r?\n[ \t]+ENDWORD\b";

【讨论】:

  • 谢谢第四只鸟!我稍微简化了正则表达式,但似乎仍然有效。 var pattern = @"(WORD)\b.*(?:\n\s(?!.*WORD\b).*)*\n\s*(ENDWORD)\b";
【解决方案2】:

这将是一个从末尾开始的非贪婪正则表达式:

编辑:忘记了'.'包括所有字符,但不包括换行符。

"WORD(\n|.)+?ENDTHING"

使用RightToLeft 选项:

Regex.Matches(input, pattern, RegexOptions.RightToLeft)

我用你在https://rextester.com/tester上的输入文本对其进行了测试

【讨论】:

  • 如果您可以提供一个工作示例,那将是一个很好的解决方案,因为它似乎是一个更简单的解决方案,如果我插入您的模式(指定 RightToLeft 选项),它不会返回任何匹配项.
  • 正则表达式已更新:忘记了 '.'包括所有字符,但不包括换行符
【解决方案3】:

我喜欢简单的解决方案

var result = text.Substring(0, text.LastIndexOf("ENDWORD")).Split(new[] {"WORD"},StringSplitOptions.None);

【讨论】:

    【解决方案4】:

    进一步研究后,似乎有一个更简单的解决方案。我的问题可能引起了一些混乱,因为除了它们的位置之外,WORD 和 ENDWORD 之间没有任何关系。这是简化的模式和示例。

    void Main()
    {
        var text =
        @"WORD
        [asdf] ---
        123/\*&
        WORD   
        [asdf] ---
        123/\*&
        ENDTHING
        [asdf] ---
        123/\*&";
    
        var pattern = $"(WORD)(?:(?!WORD\\b).|\\n)*(ENDTHING)";
        Regex rgx = new Regex(pattern);
        foreach (Match match in rgx.Matches(text))
        {
            match.Dump();
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-12-14
      • 1970-01-01
      • 2022-07-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-07-07
      • 1970-01-01
      相关资源
      最近更新 更多