在两个字符串之间找到所有的子字符串

12

我需要从字符串中获取所有的子字符串。
例如:

StringParser.GetSubstrings("[start]aaaaaa[end] wwwww [start]cccccc[end]", "[start]", "[end]");

假设我们只有一层嵌套,要返回两个字符串 "aaaaaa" 和 "cccccc"。我不确定是否需要使用正则表达式,但我认为它可能会有用。


一级嵌套意味着[start]xxx[start]yyy[end]zzz[end]是可能的吗? - kennytm
如果你是为了解析HTML或XML而这样做,那么有更好的方法... - Randolpho
5个回答

34
private IEnumerable<string> GetSubStrings(string input, string start, string end)
{
    Regex r = new Regex(Regex.Escape(start) + "(.*?)" + Regex.Escape(end));
    MatchCollection matches = r.Matches(input);
    foreach (Match match in matches)
        yield return match.Groups[1].Value;
}

6
这里有一个解决方案,它不使用正则表达式,也不考虑嵌套问题。
public static IEnumerable<string> EnclosedStrings(
    this string s, 
    string begin, 
    string end)
{
    int beginPos = s.IndexOf(begin, 0);
    while (beginPos >= 0)
    {
        int start = beginPos + begin.Length;
        int stop = s.IndexOf(end, start);
        if (stop < 0)
            yield break;
        yield return s.Substring(start, stop - start);
        beginPos = s.IndexOf(begin, stop+end.Length);
    }           
}

2

你需要更好地定义规则来管理你的匹配需求。 当构建任何类型的匹配或搜索代码时,你需要非常清楚你预期的输入和需要产生的输出。如果你不认真考虑这些问题,很容易产生错误的代码。话虽如此...

你应该能够使用正则表达式。 嵌套可能会使它稍微复杂一些,但仍然可以做到(取决于你在嵌套情况下希望匹配什么)。像这样的东西应该能够让你入门:

var start = "[start]";
var end = "[end]";
var regEx = new Regex(String.Format("{0}(.*){1}", Regex.Escape(start), Regex.Escape(end)));
var source = "[start]aaaaaa[end] wwwww [start]cccccc[end]";
var matches = regEx.Match( source );

将上面的代码封装成符合您需求的函数应该很简单。


2
您可以使用正则表达式,但请记住在参数上调用Regex.Escape
public static IEnumerable<string> GetSubStrings(
   string text,
   string start,
   string end)
{
    string regex = string.Format("{0}(.*?){1}",
        Regex.Escape(start), 
        Regex.Escape(end));

    return Regex.Matches(text, regex, RegexOptions.Singleline)
        .Cast<Match>()
        .Select(match => match.Groups[1].Value);
}

我还添加了SingleLine选项,这样即使在您的文本中有换行符,它也会匹配。

0

我感到无聊,于是我做了一个毫无用处的微型基准测试。在我的数据集中,字符串长度最长可达7k个字符,还有<b>标签作为起始/结束参数。这"证明"了我的猜想,即juharr的解决方案是三种方案中整体最快的。

结果(1000000次迭代*20个测试用例):

juharr: 6371ms
Jake: 6825ms
Mark Byers: 82063ms

注意:在我的数据集上编译的正则表达式并没有提高速度。


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