string.IndexOf搜索整个单词匹配

时间:2014-06-26 18:04:10

标签: c# regex string substring indexof

我正在寻找一种搜索字符串以获得完全匹配或完整字匹配的方法。 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次搜索。在这种情况下,仅仅知道存在完全匹配是不够的。我需要知道它在字符串中的位置。

任何建议都将受到赞赏。

6 个答案:

答案 0 :(得分:9)

您可以使用Regex

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

答案 1 :(得分:1)

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

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

答案 2 :(得分:1)

为了使接受的答案更安全一些(因为 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;

答案 3 :(得分:0)

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

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

在总数之前给予额外的空间。因为SUBTOTAL不会出现这种情况,所以它应该跳过您不想要的单词,只是寻找孤立的TOTAL

答案 4 :(得分:0)

我推荐L.B.的Regex解决方案。但是,如果你不能使用Regex,那么你可以使用String.LastIndexOf(&#34; TOTAL&#34;)。假设TOTAL总是在SUBTOTAL之后出现?

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

答案 5 :(得分:0)

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

    private void fillRect( int delay, Graphics2D g, int x, int y, int width, int height ) {
        Timer timer = new Timer(delay, new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                g.setColor(Color.cyan);
                g.fillRect(x, y, width, height);
                g.setColor(Color.black);
            }
        });
        timer.setRepeats( false );
        timer.start();
    }

请参见C# demo

var text = "SUBTOTAL 34.37 TAX TOTAL 37.43"; var idx = Regex.Match(text, @"\bTOTAL\b").Index; // => 19 \bTOTAL\b匹配时,未用任何其他字母,数字或下划线括起来。

如果您需要将一个单词当作一个完整的单词(如果包含下划线的话),请使用

TOTAL

其中var idx = Regex.Match(text, @"(?<![^\W_])TOTAL(?![^\W_])").Index; 是否定的向后查找,如果存在非单词以外的字符并且在当前位置的左侧紧跟下划线,则匹配失败,因此,可以从字符串位置开始,或不是数字或字母的字符),并且(?<![^\W_])是类似的否定前瞻,仅当字符串位置的末尾或除字母或数字紧邻的字符之外的字符时才匹配当前位置。

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

(?![^\W_])

其中var idx = Regex.Match(text, @"(?<!\S)TOTAL(?!\S)").Index; 要求在左侧紧随字符串的开头或空白,而(?<!\S)要求在右侧紧随字符串的结尾或空白。

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