查找忽略指定字符的子字符串

Posted

技术标签:

【中文标题】查找忽略指定字符的子字符串【英文标题】:Find substring ignoring specified characters 【发布时间】:2011-02-05 06:18:54 【问题描述】:

你们中是否有人知道一种简单/干净的方法来在字符串中查找子字符串,同时忽略一些指定的字符来查找它。我认为一个例子可以更好地解释事情:

string: "你好,-this- 是一个字符串" 要查找的子字符串:“Hello this” 要忽略的字符: "," 和 "-" 找到子字符串,结果:“你好,-this”

使用正则表达式对我来说不是必需的,但我添加了标签,因为它感觉相关。

更新:

为了使要求更清晰:我需要生成的子字符串 with 被忽略的字符,而不仅仅是给定子字符串存在的指示。

更新 2: 你们中的一些人对这个例子读得太多了,对不起,我会给出另一个应该可行的场景:

字符串: "?A&3/3/C)412&" 要查找的子字符串: "A41" 要忽略的字符:“&”、“/”、“3”、“C”、“)” 找到子字符串,结果: "A&3/3/C)41"

作为奖励(本身不是必需的),如果假设 要查找的子字符串 上不会有被忽略的字符也不安全,那就太好了,例如:鉴于最后一个例子我们应该能够做到:

要查找的子字符串: "A3C412&" 要忽略的字符:“&”、“/”、“3”、“C”、“)” 找到子串,结果: "A&3/3/C)412&"

对不起,如果我之前不清楚,或者我仍然不清楚:)。

更新 3:

感谢所有提供帮助的人!这是我目前正在使用的实现:

http://www.pastebin.com/pYHbb43Z

这里有一些测试:

http://www.pastebin.com/qh01GSx2

我正在使用一些我不包括在内的自定义扩展方法,但我相信它们应该是不言自明的(如果你愿意,我会添加它们) 我已经为实施和测试采纳了您的很多想法,但我正在向@PierrOz 提供答案,因为他是第一个,并为我指明了正确的方向。 随时就 impl 的当前状态继续提供建议作为替代解决方案或 cmets。如果你喜欢。

【问题讨论】:

@Fredy 看看我更新的回复,如果我理解正确,应该涵盖您更新的场景。 @Fredy - 是否可以安全地得出结论,您希望输入字符串和搜索字符串在搜索之前都清除不需要的字符?如果是这样,下面我提供了一个同时使用 RegEx 和字符串搜索的解决方案。 @Ahmad - 我喜欢你的更新,我会从那里得到一些想法,谢谢。 @Jamie 您可以假设要搜索的字符串上没有“忽略的字符”,但如果您允许这样做会更好。在输入字符串的情况下,它肯定会有“忽略的字符”,这就是想法:) 【参考方案1】:

在你的例子中你会这样做:

string input = "Hello, -this-, is a string";
string ignore = "[-,]*";
Regex r = new Regex(string.Format("H0e0l0l0o0 0t0h0i0s0", ignore));
Match m = r.Match(input);
return m.Success ? m.Value : string.Empty;

您将动态构建包含所有要忽略的字符的部分 [-, ],并将此部分插入到查询的所有字符之间。

注意类[]中的'-':放在开头或结尾

所以更一般地说,它会给出如下内容:

public string Test(string query, string input, char[] ignorelist)

    string ignorePattern = "[";
    for (int i=0; i<ignoreList.Length; i++)
    
        if (ignoreList[i] == '-')
        
            ignorePattern.Insert(1, "-");
        
        else
        
            ignorePattern += ignoreList[i];
        
    

    ignorePattern += "]*";

    for (int i = 0; i < query.Length; i++)
    
        pattern += query[0] + ignorepattern;
    

    Regex r = new Regex(pattern);
    Match m = r.Match(input);
    return m.IsSuccess ? m.Value : string.Empty;

【讨论】:

嗨!我已经考虑过这个选项,它绝对适合我。我正在寻找不需要我动态构建正则表达式的更清洁的东西。但是,如果没有出现类似的情况,您应该得到“答复”。问候。 是的,我不确定我们能否避免这样的事情。此外,在忽略列表中,我们必须处理诸如“?”之类的字符。或“+”以及正则表达式语法中使用的所有。测试方法还有一些工作:) 你是对的,但如果把它留给我作为练习也没关系:)。如果我以这种方式实现它,我会尽量记住用更通用的实现或指向它的链接来更新问题。非常感谢您的帮助。【参考方案2】:

这是一个非正则表达式字符串扩展选项:

public static class StringExtensions

    public static bool SubstringSearch(this string s, string value, char[] ignoreChars, out string result)
    
        if (String.IsNullOrEmpty(value))
            throw new ArgumentException("Search value cannot be null or empty.", "value");

        bool found = false;
        int matches = 0;
        int startIndex = -1;
        int length = 0;

        for (int i = 0; i < s.Length && !found; i++)
        
            if (startIndex == -1)
            
                if (s[i] == value[0])
                
                    startIndex = i;
                    ++matches;
                    ++length;
                
            
            else
            
                if (s[i] == value[matches])
                
                    ++matches;
                    ++length;
                
                else if (ignoreChars != null && ignoreChars.Contains(s[i]))
                
                    ++length;
                
                else
                
                    startIndex = -1;
                    matches = 0;
                    length = 0;
                
            

            found = (matches == value.Length);
        

        if (found)
        
            result = s.Substring(startIndex, length);
        
        else
        
            result = null;
        
        return found;
    

【讨论】:

【参考方案3】:

编辑:这是一个更新的解决方案,解决了您最近更新中的要点。这个想法是一样的,除非你有一个子字符串,它需要在每个字符之间插入忽略模式。如果子字符串包含空格,它将在空格上拆分并在这些单词之间插入忽略模式。如果您不需要后一种功能(这更符合您的原始问题),那么您可以删除提供该模式的 Splitif 检查。

请注意,这种方法不会是最有效的。

string input = @"foo ?A&3/3/C)412& bar A341C2";
string substring = "A41";
string[] ignoredChars =  "&", "/", "3", "C", ")" ;

// builds up the ignored pattern and ensures a dash char is placed at the end to avoid unintended ranges
string ignoredPattern = String.Concat("[",
                            String.Join("", ignoredChars.Where(c => c != "-")
                                                        .Select(c => Regex.Escape(c)).ToArray()),
                            (ignoredChars.Contains("-") ? "-" : ""),
                            "]*?");

string[] substrings = substring.Split(new[]  ' ' , StringSplitOptions.RemoveEmptyEntries);

string pattern = "";
if (substrings.Length > 1)

    pattern = String.Join(ignoredPattern, substrings);

else

    pattern = String.Join(ignoredPattern, substring.Select(c => c.ToString()).ToArray());


foreach (Match match in Regex.Matches(input, pattern))

    Console.WriteLine("Index: 0 -- Match: 1", match.Index, match.Value);


试试这个解决方案:
string input = "Hello, -this- is a string";
string[] searchStrings =  "Hello", "this" ;
string pattern = String.Join(@"\W+", searchStrings);

foreach (Match match in Regex.Matches(input, pattern))

    Console.WriteLine(match.Value);

\W+ 将匹配任何非字母数字字符。如果您想自己指定它们,可以将其替换为要忽略的字符的字符类,例如 [ ,.-]+(始终将短划线字符放在开头或结尾以避免意外的范围指定)。另外,如果您需要忽略大小写,请使用RegexOptions.IgnoreCase

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

如果你的子字符串是一个完整的字符串形式,比如“Hello this”,你可以很容易的把它变成searchString的数组形式:

string[] searchString = substring.Split(new[]  ' ' ,
                            StringSplitOptions.RemoveEmptyEntries);

【讨论】:

【参考方案4】:

此代码将满足您的需求,但我建议您对其进行修改以更好地满足您的需求:

string resultString = null;

try

    resultString = Regex.Match(subjectString, "Hello[, -]*this", RegexOptions.IgnoreCase).Value;

catch (ArgumentException ex)

    // Syntax error in the regular expression

【讨论】:

谢谢,但我需要更通用的东西,我的例子就是这样 :)【参考方案5】:

您可以使用单个正则表达式来执行此操作,但这会非常乏味,因为您需要在每个字符之后测试零个或多个被忽略的字符。用Regex.Replace(subject, "[-,]", ""); 去除所有被忽略的字符可能更容易,然后测试子字符串是否存在。

或单一的正则表达式方式

Regex.IsMatch(subject, "H[-,]*e[-,]*l[-,]*l[-,]*o[-,]* [-,]*t[-,]*h[-,]*i[-,]*s[-,]*")

【讨论】:

嗨,我想我不能删除字符,因为我需要生成的带有字符的子字符串。谢谢!【参考方案6】:

这是一种使用字符串解析的非正则表达式方法。

    private string GetSubstring()

    
        string searchString = "Hello, -this- is a string";
        string searchStringWithoutUnwantedChars = searchString.Replace(",", "").Replace("-", "");

        string desiredString = string.Empty;
        if(searchStringWithoutUnwantedChars.Contains("Hello this"))
            desiredString = searchString.Substring(searchString.IndexOf("Hello"), searchString.IndexOf("this") + 4);

        return desiredString;
    

【讨论】:

【参考方案7】:

你可以这样做,因为大多数这些答案都需要以某种形式重建字符串。

string1 是你要查看的字符串

//Create a List(Of string) that contains the ignored characters'
List<string> ignoredCharacters = new List<string>();

//Add all of the characters you wish to ignore in the method you choose

//Use a function here to get a return

public bool subStringExist(List<string> ignoredCharacters, string myString, string toMatch)

    //Copy Your string to a temp

    string tempString = myString;
    bool match = false;

    //Replace Everything that you don't want

    foreach (string item in ignoredCharacters)
    
        tempString = tempString.Replace(item, "");
    

    //Check if your substring exist
    if (tempString.Contains(toMatch))
    
        match = true;
    
    return match;

【讨论】:

【参考方案8】:

您始终可以结合使用 RegEx 和字符串搜索

public class RegExpression 

  public static void Example(string input, string ignore, string find)
  
     string output = string.Format("Input: 10Ignore: 20Find: 300", Environment.NewLine, input, ignore, find);
     if (SanitizeText(input, ignore).ToString().Contains(SanitizeText(find, ignore)))
        Console.WriteLine(output + "was matched");
     else
        Console.WriteLine(output + "was NOT matched");
     Console.WriteLine();
  

  public static string SanitizeText(string input, string ignore)
  
     Regex reg = new Regex("[^" + ignore + "]");
     StringBuilder newInput = new StringBuilder();
     foreach (Match m in reg.Matches(input))
     
        newInput.Append(m.Value);
     
     return newInput.ToString();
  

用法会像

RegExpression.Example("Hello, -this- is a string", "-,", "Hello this");  //Should match
RegExpression.Example("Hello, -this- is a string", "-,", "Hello this2"); //Should not match
RegExpression.Example("?A&3/3/C)412&", "&/3C\\)", "A41"); // Should match
RegExpression.Example("?A&3/3/C) 412&", "&/3C\\)", "A41"); // Should not match
RegExpression.Example("?A&3/3/C)412&", "&/3C\\)", "A3C412&"); // Should match

输出

输入:你好,-this- 是一个字符串 忽视: -, 查找:你好这个

匹配

输入:你好,-this- 是一个字符串 忽视: -, 查找:你好这个2

不匹配

输入:?A&3/3/C)412& 忽略:&/3C) 查找:A41

匹配

输入:?A&3/3/C) 412& 忽略:&/3C) 查找:A41

不匹配

输入:?A&3/3/C)412& 忽略:&/3C) 查找:A3C412&

匹配

【讨论】:

以上是关于查找忽略指定字符的子字符串的主要内容,如果未能解决你的问题,请参考以下文章

PB中取字符串子串的函数是啥

C++编程,查找字符串子串并替换。

字符串子串的查找

C语言中如何用一个字符串替换一个主串中的子串

数组篇在python中如何查找最长字符串子串

excel或wps查找文本字符串子串或拆分字符串公式