在一个子字符串后面查找索引

10
假设你有一个字符串("haystack"), 以及你想要搜索的子字符串("needle"):
 string haystack = "D0B11234 AM21ANP AM23AN1";
 string needle = "AM21AN";   

我正在寻找一种方法来查找所需子字符串之后的索引或子字符串。
调用IndexOf()会返回针的起始位置,因此在这种情况下index = 9
int index = haystack.IndexOf(needle);

我的最初想法是使用LastIndexOf(),但它返回的是针在干草堆中最后一次出现的起始索引。
正如这个类似的问题(以及可能的其他问题)所回答的那样,如果你想定位紧随needle之后的字符,则需要像这样通过增加针的长度来增加index
int index = haystack.IndexOf(needle);
int indexAfterNeedle = index + needle.Length;

除了每次键入index + needle.Length之外,是否存在一种方法(现有的或易于扩展),可以确定子字符串的结束索引?


1
结尾不就是起始位置加上长度吗? - Eric Lippert
1
@EricLippert 结尾就是起始位置加上长度!这可能是一件微不足道的事情,但是经过这个问题的思考,我想知道C#是否包含一个返回字符串结尾而不是开头(像IndexOf一样)的方法。我目前使用的方法是startValueFromIndexOf + string.Length,只是想知道是否有其他可用的方法。 - levelonehuman
@CodeCaster startIndex 只是决定从哪里开始查找;我不认为它会影响 IndexOf() 实际返回的值。 - levelonehuman
2
@codeCaster,很容易理解他想做什么。也许不清楚为什么它很重要,但那是另一回事了。对于OP:没有。使用startIdx并添加长度是简短而简单的。没有必要增加额外的复杂性来进一步简化它。 - leigero
1
@CodeCaster 很不错! 谢谢你。 - levelonehuman
显示剩余8条评论
2个回答

10

不,BCL中没有内建的功能。

通过扩展方法很容易自己添加:

public static int EndIndexOf(this string source, string value)
{
    int index = source.IndexOf(value);
    if (index >= 0)
    {
        index += value.Length;
    }

    return index;
}

演示:

string testString = "D0B11234 AM21ANP AM23AN1";
string stringToSearch = "AM21AN";   

int endIndex = testString.EndIndexOf(stringToSearch);

Console.WriteLine(testString);
Console.WriteLine(endIndex);
Console.WriteLine(testString.Substring(endIndex));

输出:

D0B11234 AM21ANP AM23AN1
15
P AM23AN1

根据您的要求,这可能看起来像是一个 off-by-one 错误,因此您可能希望将其更改为 index += value.Length - 1,以返回value的最后一个字符的位置,而不是那个字符之后的索引。
您还可以添加一个重载方法,带有一个名为int startIndex的参数,并且从上面的方法中实际调用该方法,并使用startIndex: 0
请确保为扩展方法添加错误处理,例如抛出ArgumentNullException等异常。
另外,如果要查找的字符串位于源字符串的末尾,则不能使用此方法返回的值来获取源字符串的子字符串,因为它将超出源字符串的范围。

2
你是不是想把 value.Length 加到索引上,而不是 source.Length - E. Moffat
@E.Moffat 是的,这就是在吃饭时在Notepad++中快速复制粘贴示例的结果。 - CodeCaster
1
我很感激你的回答!即使这是一件微不足道的事情,扩展方法对我来说仍然是新鲜事物,我从未想过这一点 - 所以感谢你教给我一些东西! - levelonehuman
我猜你可能已经知道了,但你可以将其简化为 return (index >= 0) ? index + value.Length : index; - sab669
2
只是为了其他读者,@levelonehuman和我自己的缘故,我链接了这个关于扩展方法的MSDN页面,因为我在实现它方面经验不太丰富。 - sab669

2

如果您的需求超出了精确模式匹配,而且不使用IndexOf()函数,您可以考虑使用正则表达式:

这将允许您执行以下操作: 在搜索字符串后面查找第一个非空格字符的位置是什么?

string testString = "D0B11234 AM21ANP AM23AN1";
string stringToSearch = "AM21AN";   
Match m = Regex.Match(testString,stringToSearch);
int endpos = m.Index + m.Length;

Match m2 = Regex.Match(testString,@"(" + Regex.Escape(stringToSearch) + @")\s*(\S)");

int nonwspos = m2.Groups[2].Index;

这将返回搜索字符串后的P位置,即使在字符串之后有空格,也会返回正确位置。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接