检查字符串是不是包含模式,忽略位置。并返回项目匹配的索引

Posted

技术标签:

【中文标题】检查字符串是不是包含模式,忽略位置。并返回项目匹配的索引【英文标题】:Checking if string contains pattern, with places ignored. And returning the index from which the items match检查字符串是否包含模式,忽略位置。并返回项目匹配的索引 【发布时间】:2021-09-18 00:14:54 【问题描述】:

我已经实现了这样一个方法:

static void Main(string[] args)

    string s = "05 AA 06 15 14";
    var pattern1 = "05 AA";
    var pattern2 = "06 15";
    var pattern3 = "AA ** 15";
    var pattern4 = "15 14";
    Console.WriteLine(CheckTextContains2(s, pattern1));
    Console.WriteLine(CheckTextContains2(s, pattern2));
    Console.WriteLine(CheckTextContains2(s, pattern3));
    Console.WriteLine(CheckTextContains2(s, pattern4));

private static int CheckTextContains2(string text, string pattern)

    if (text.Length < pattern.Length)
        return -1;
    for (int i = 0; i < text.Length - pattern.Length +1; i++)
    
        for (int j = 0; j < pattern.Length; j++)
        
            if (pattern[j] == '*')
                continue;
            else if (text[j + i] != pattern[j])
                break;
            else if (j == pattern.Length -1)
                return i;
        
    
    return -1;

该方法检查给定模式是否在字符串中,但忽略字符“*”并返回起始索引。

但这似乎非常不理想,我可以通过正则表达式获得它吗?

【问题讨论】:

这能回答你的问题吗? Matching strings with wildcard @Sinatr 不,在我的情况下,'*' 只忽略一个字符。我需要知道开始索引。 是的。您可以使用Regex.Match(s, pattern) 来检查位置。 pattern3 的唯一变化是您必须将 * 替换为 .。 DEMO 查找位置的示例行可能类似于 var posP1 = Regex.Match(s, pattern1) is Success: true m1 ? m1.Index : -1; @SebastianSchumann:一个很好的答案。太糟糕了,因为您不小心将它发布到评论字段中,OP 将无法接受它...... @Heinzi 这不是偶然作为评论发布的。这是故意的。我希望有人接受这个想法并在其周围添加一些上下文信息。 【参考方案1】:

是的。您可以使用Regex.Match(s, pattern) 来检查位置。 pattern3 的唯一变化是您必须将 * 替换为 .

代码可能如下所示:

string s = "05 AA 06 15 14";
var pattern1 = "05 AA";
var pattern2 = "06 15";
var pattern3 = "AA .. 15";
var pattern4 = "15 14";

var posP1 = Regex.Match(s, pattern1) is  Success: true  m1 ? m1.Index : -1;
var posP2 = Regex.Match(s, pattern2) is  Success: true  m2 ? m2.Index : -1;
var posP3 = Regex.Match(s, pattern3) is  Success: true  m3 ? m3.Index : -1;
var posP4 = Regex.Match(s, pattern4) is  Success: true  m4 ? m4.Index : -1;

Console.WriteLine(posP1);
Console.WriteLine(posP2);
Console.WriteLine(posP3);
Console.WriteLine(posP4);

输出是:

0
6
3
9

DEMO

解释:

正则表达式中的. 是单字符通配符。模式中的所有其他字符都不会影响正则表达式,并将用作要查找的固定文本。对于\[].()*+ 之类的字符,您必须小心谨慎。但是,如果您的模式不包含任何这些正则表达式将像 string.IndexOf() 一样工作。

Regex.Match() 方法将返回一个 Match 实例,其中包含必须检查 Success 的属性。示例代码使用模式匹配来完成它,以便能够将其写在一行中。

请记住,您应该使用this._pattern1Finder = new Regex(pattern1, RegexOptions.Compiled) 缓存正则表达式,以避免在每次执行时构造正则表达式。调用看起来像this._pattern1Finder.Match(s) is ...,而不是使用Regex 的静态方法。这取决于您尝试将相同模式与各种输入匹配的频率。

【讨论】:

【参考方案2】:

如果比赛是:越短越好,我想介绍一下:

private static int CheckTextContains(string text, string pattern)
    
        if (text.Length >= pattern.Length) 
            for (var offset = 0; offset < text.Length - pattern.Length; offset++) 
                if (!pattern.Where((t, i) => '*' != t && t != text[i + offset]).Any())
                    return offset;
            
        
        return -1;
    

这是一个精简的、可读性和可维护性较差的版本:

private static int CheckTextContains(string text, string pattern)
    
        if (text.Length >= pattern.Length) 
            for (var offset = 0; offset < text.Length - pattern.Length; offset++) 
                if (IsMatch(offset))
                    return offset;
            
        
        return -1;

        bool IsMatch(int offset) 
            for (var i = 0; i < pattern.Length; i++)
            
                if ('*' != pattern[i] && pattern[i] != text[i+offset]))
                    return false;
            
            return true;
        
    

【讨论】:

以上是关于检查字符串是不是包含模式,忽略位置。并返回项目匹配的索引的主要内容,如果未能解决你的问题,请参考以下文章

雪花 - 检查模式并返回该模式中的子字符串

检查字符串是不是包含子字符串列表并保存匹配的子字符串

正则表达式1

局部匹配忽略案例和变音符号

用python中re.match匹配为啥一直是None?

Python3正则表达式