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

时间:2010-04-07 13:05:09

标签: c# .net regex substring

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

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

使用正则表达式不是我的要求,但我添加了标签,因为它感觉相关。

更新

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

更新2: 你们当中有些人正在阅读这个例子,对不起,我会给出另一种应该有效的方案:

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

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

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

对不起,如果我以前不清楚,或者我不是:)。

更新3:

感谢所有帮助过的人!这是我现在正在使用的实现:

以下是一些测试:

我正在使用一些我不包括的自定义扩展方法,但我相信它们应该是自我解释的(如果你愿意,我会添加它们) 我已经对实施和测试采取了很多你的想法,但我给@PierrOz的答案,因为他是第一,并指出了我正确的方向。 随意提供建议作为替代解决方案或对当前状态的评论。如果你愿意的话。

8 个答案:

答案 0 :(得分:1)

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

string input = "Hello, -this-, is a string";
string ignore = "[-,]*";
Regex r = new Regex(string.Format("H{0}e{0}l{0}l{0}o{0} {0}t{0}h{0}i{0}s{0}", 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;
}

答案 1 :(得分:1)

编辑:这是针对您最近更新中的要点的更新解决方案。这个想法是相同的,除非你有一个子字符串,它需要在每个字符之间插入忽略模式。如果子字符串包含空格,它将在空格上分割并在这些单词之间插入忽略模式。如果您不需要后一种功能(更符合原始问题),那么您可以删除提供该模式的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);

答案 2 :(得分:1)

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

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 :(得分:0)

此代码可以满足您的需求,但我建议您修改它以更好地满足您的需求:

string resultString = null;

try
{
    resultString = Regex.Match(subjectString, "Hello[, -]*this", RegexOptions.IgnoreCase).Value;
}
catch (ArgumentException ex)
{
    // Syntax error in the regular expression
}

答案 4 :(得分:0)

你可以用一个正则表达式做到这一点,但是在你需要测试零个或多个被忽略的字符后,每个字符都会非常繁琐。使用Regex.Replace(subject, "[-,]", "");去除所有被忽略的字符可能更容易,然后测试子字符串是否存在。

或单一的Regex方式

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

答案 5 :(得分:0)

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

    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;
    }

答案 6 :(得分:0)

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

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;
}

答案 7 :(得分:0)

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

public class RegExpression {

  public static void Example(string input, string ignore, string find)
  {
     string output = string.Format("Input: {1}{0}Ignore: {2}{0}Find: {3}{0}{0}", 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&amp; 3/3 / C)412&amp; 忽略:&amp; / 3C) 发现:A41

匹配

输入:?A&amp; 3/3 / C)412&amp; 忽略:&amp; / 3C) 发现:A41

未匹配

输入:?A&amp; 3/3 / C)412&amp; 忽略:&amp; / 3C) 发现:A3C412&amp;

匹配