【问题标题】:string.IndexOf search for whole word matchstring.IndexOf 搜索整个单词匹配
【发布时间】:2014-08-17 16:55:05
【问题描述】:

我正在寻找一种方法来搜索字符串以进行完全匹配或整个单词匹配。 RegEx.MatchRegEx.IsMatch 似乎无法让我到达我想去的地方。
考虑以下场景:

namespace test
{
    class Program
    {
        static void Main(string[] args)
        {
            string str = "SUBTOTAL 34.37 TAX TOTAL 37.43";
            int indx = str.IndexOf("TOTAL");
            string amount = str.Substring(indx + "TOTAL".Length, 10);
            string strAmount = Regex.Replace(amount, "[^.0-9]", "");

            Console.WriteLine(strAmount);
            Console.WriteLine("Press any key to continue...");
            Console.ReadKey();
        }
    }
}

以上代码的输出为:

// 34.37
// Press any key to continue...

问题是,我不想要 SUBTOTAL,但 IndexOf 找到了 TOTAL 一词的第一次出现在 SUBTOTAL 然后产生不正确的值 34.37。

所以问题是,有没有办法强制 IndexOf 只找到一个完全匹配,或者有没有另一种方法来强制完全匹配整个单词,这样我就可以找到那个完全匹配的索引,然后执行一些有用的功能。 RegEx.IsMatchRegEx.Match 是,据我所知,只是 boolean 搜索。在这种情况下,仅仅知道存在精确匹配是不够的。我需要知道它在字符串中的位置。

任何建议将不胜感激。

【问题讨论】:

  • str.IndexOf(" TOTAL "); 但是很丑。

标签: c# regex string substring indexof


【解决方案1】:

你可以使用正则表达式

string str = "SUBTOTAL 34.37 TAX TOTAL 37.43";
var indx = Regex.Match(str, @"\WTOTAL\W").Index; // will be 18

【讨论】:

  • 谢谢!这样干净多了!谁知道 RegEx.Match 上有一个“.Index”? :) :) :)
  • 不久前,有一篇关于此答案的帖子使用正则表达式模式返回与“TOTAL”完全匹配的数字。其他人看到了吗?有人愿意权衡这种模式吗?
  • @DJ 你在寻找类似var val = Regex.Match(str, @"\WTOTAL\W\s*([0-9\.]+)").Groups[1].Value;的东西吗
  • 哇!我必须了解更多关于 RegEx 的信息。它看起来非常强大,如果不是很直观的话。谢谢 LB!
【解决方案2】:

我的方法比接受的答案更快,因为它不使用正则表达式。

string str = "SUBTOTAL 34.37 TAX TOTAL 37.43";
var indx = str.IndexOfWholeWord("TOTAL");

public static int IndexOfWholeWord(this string str, string word)
{
    for (int j = 0; j < str.Length && 
        (j = str.IndexOf(word, j, StringComparison.Ordinal)) >= 0; j++)
        if ((j == 0 || !char.IsLetterOrDigit(str, j - 1)) && 
            (j + word.Length == str.Length || !char.IsLetterOrDigit(str, j + word.Length)))
            return j;
    return -1;
}

【讨论】:

  • 这也更灵活,因为如果 TOTAL 不在行中,它会返回 -1。上面的正则表达式返回 0。
【解决方案3】:

您可以使用word boundaries, \bMatch.Index property

var text = "SUBTOTAL 34.37 TAX TOTAL 37.43";
var idx = Regex.Match(text, @"\bTOTAL\b").Index;
// => 19

请参阅C# demo

\bTOTAL\bTOTAL 不包含任何其他字母、数字或下划线时匹配。

如果您需要将一个单词用下划线括起来算作一个完整的单词,请使用

var idx = Regex.Match(text, @"(?<![^\W_])TOTAL(?![^\W_])").Index;

其中(?&lt;![^\W_]) 是一个否定的lookbehind,如果在当前位置的左侧有一个非单词和下划线以外的字符,则匹配失败(因此,可以是字符串位置的开头,或者char 不是数字也不是字母),(?![^\W_]) 是一个类似的负前瞻,仅在当前位置右侧有一个字符串结尾位置或除字母或数字之外的字符时才匹配。

如果边界是空格或字符串使用的开始/结束

var idx = Regex.Match(text, @"(?<!\S)TOTAL(?!\S)").Index;

其中(?&lt;!\S) 需要字符串的开头或紧靠左侧的空格,(?!\S) 需要字符串的结尾或右侧的空格。

注意\b(?&lt;!...)(?!...)non-consuming patterns,即匹配这些模式时正则表达式索引不会前进,因此,您可以得到准确的位置您搜索的词。

【讨论】:

    【解决方案4】:

    为了让接受的答案更安全一些(因为IndexOf 返回 -1 表示不匹配):

    string pattern = String.Format(@"\b{0}\b", findTxt);
    Match mtc = Regex.Match(queryTxt, pattern);
    if (mtc.Success)
    {
        return mtc.Index;
    }
    else
        return -1;
    

    【讨论】:

      【解决方案5】:

      虽然这可能是仅适用于您的示例的 hack,但请尝试

      string amount = str.Substring(indx + " TOTAL".Length, 10);
      

      在总计前多留一个空格。因为SUBTOTAL 不会发生这种情况,所以它应该跳过你不想要的单词,只寻找一个孤立的TOTAL

      【讨论】:

      • 哈哈!!!我怎么没看到!这有点“hacky”,但仅以我为例,它应该可以工作。我真的很想看看是否有办法以更干净的方法强制整个单词匹配,但如果我在一天左右没有看到更精致的答案,我会将其标记为答案。非常感谢!!! :)
      【解决方案6】:

      我推荐 L.B. 的 Regex 解决方案。也是,但如果你不能使用正则表达式,那么你可以使用 String.LastIndexOf("TOTAL")。假设 TOTAL 总是在 SUBTOTAL 之后?

      http://msdn.microsoft.com/en-us/library/system.string.lastindexof(v=vs.110).aspx

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-06-07
        • 1970-01-01
        • 1970-01-01
        • 2021-07-11
        • 2012-03-29
        • 1970-01-01
        相关资源
        最近更新 更多