【问题标题】:How to find string with beginning pattern and contains pattern如何查找具有开头模式并包含模式的字符串
【发布时间】:2019-01-10 17:50:56
【问题描述】:

我一直在研究this post,试图组合一个c# regex,它执行以下操作:查找一个字符串是否包含另一个以某些字母开头并包含某些字符的字符串。

这里是 1 个干草堆字符串的具体示例:

NOT SUPPCODE{900mm,1500mm} and IDU{true}

我需要发现 haystack 字符串是否包含 NOT(最好不区分大小写)后跟 1 个空格,紧接着是包含以下 3 个字符的完整空格“单词”(按顺序排列,但不是相邻):{,}。换句话说,必须有 1 个或多个逗号用左/右花括号括起来。 大括号内的空格很好,但SUPPCODE(在本例中)和左大括号之间不能有空格。

我的 haystack 示例实际上与该模式匹配,因为有一个 NOT(不需要在字符串的开头)后跟一个空格,然后是一系列包含左花括号的字符大括号、逗号和右花括号。这 3 个字符不会相邻。

这是我根据上面提到的不适合我的帖子整理的 c# 代码:

public static bool ContainsRegex(string haystack, string startsWith, string contains) {
   var regex = new Regex("(?=.*" + contains + ")^" + startsWith);
   int matches = regex.Matches(haystack).Count;
   return matches > 0;
}

这样称呼:

bool isFound = ContainsRegex("NOT SUPPCODE{900mm,1500mm} and IDU{true}", "NOT ", "{,}");

这些字符串参数当然是动态的,并且在运行时总是不同的。

即使在某些情况下(如上所示)它应该返回 true,我的函数也总是返回 false。

下面是一些否定测试字符串,相比之下,应该返回 false:

SUPPCODE{900mm,1500mm} and IDU{true} // doesn't begin with NOT
STUFF SUPPCODE{900mm,1500mm} and IDU{true} // doesn't begin with NOT
NOT SUPPCODE{900mm} and IDU{true} // no comma between curly braces
NOT SUPPCODE,5,6900mm} and IDU{true} // no left curly brace
NOTSUPPCODE{900mm,1500mm} and IDU{true} // no space between NOT and SUPPCODE
NOT SUPPCODE {900mm,1500mm} and IDU{true} // space between SUPPCODE and left curly brace

我做错了什么?

【问题讨论】:

  • 看来你想要的只是return Regex.IsMatch(haystack, @"^NOT \w+{[^{},]*,[^{}]*}")
  • Regex.IsMatch(haystack, @"(?i)^NOT\s+\w+{.*?,.*?}")
  • @WiktorStribiżew OP 说:a NOT(最好不区分大小写)
  • @JohnyL 这无关紧要。也可以写成return Regex.IsMatch(haystack, @"^NOT \w+{[^{},]*,[^{}]*}", RegexOptions.IgnoreCase)
  • @WiktorStribiżew 同意,但我们需要尊重 OP 的要求 ????

标签: c# regex


【解决方案1】:

你可以使用

public static bool ContainsRegex(string haystack, string startsWith, string contains) 
{
    var delims = contains.Select(x => x.ToString().Replace("\\", @"\\").Replace("-", @"\-").Replace("^", @"\^").Replace("]", @"\]")).ToList();
    var pat = $@"^{startsWith} \w+{Regex.Escape(contains.Substring(0,1))}[^{string.Concat(delims)}]*{Regex.Escape(contains.Substring(1,1))}[^{delims[0]}{delims[2]}]*{Regex.Escape(contains.Substring(2,1))}";
    // Console.WriteLine(pat); // => ^NOT \w+\{[^{,}]*,[^{}]*}
    return Regex.IsMatch(haystack, pat, RegexOptions.IgnoreCase);
}

这里是an example

var strs = new[] { "SUPPCODE{900mm,1500mm} and IDU{true}",
            "STUFF SUPPCODE{900mm,1500mm} and IDU{true}",
            "NOT SUPPCODE{900mm} and IDU{true}",
            "NOT SUPPCODE,5,6900mm} and IDU{true}",
            "NOTSUPPCODE{900mm,1500mm} and IDU{true}",
            "NOT SUPPCODE {900mm,1500mm} and IDU{true}",
            "NOT SUPPCODE{900mm,1500mm} and IDU{true}"};
foreach (var s in strs)
    Console.WriteLine($"{s} => {ContainsRegex(s, "NOT", "{,}")}");

输出:

SUPPCODE{900mm,1500mm} and IDU{true} => False
STUFF SUPPCODE{900mm,1500mm} and IDU{true} => False
NOT SUPPCODE{900mm} and IDU{true} => False
NOT SUPPCODE,5,6900mm} and IDU{true} => False
NOTSUPPCODE{900mm,1500mm} and IDU{true} => False
NOT SUPPCODE {900mm,1500mm} and IDU{true} => False
NOT SUPPCODE{900mm,1500mm} and IDU{true} => True

contains 参数假定只有 3 个字符:起始分隔符是第一个字符,中间一个是里面的强制字符,然后第三个字符是尾随字符。

另请参阅resulting regex demo

详情

  • ^ - 字符串开头
  • NOT - startsWith 字符串
  • - 空格
  • \w+ - 1+ 个单词字符
  • \{ - 起始分隔符
  • [^{,}]* - 除定界符以外的 0+ 个字符
  • , - 中间强制字符
  • [^{}]* - 除了开始和结束分隔符之外还有 0+ 个字符
  • } - 尾随分隔符。

【讨论】:

  • var delims 你不能用Regex.Escape吗?
  • @JohnyL 我在必要时使用Regex.Escape在字符类之外。您不能使用 Regex.Escape 转义要在字符类中使用的字符。
  • 啊,正确... 当特殊字符出现在括号中时,您不需要转义,除非是破折号和右括号
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-12-17
  • 1970-01-01
  • 2015-04-21
  • 2022-01-16
  • 2020-09-06
  • 1970-01-01
  • 2020-01-22
相关资源
最近更新 更多