代码之家  ›  专栏  ›  技术社区  ›  Denis Palnitsky

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

  •  11
  • Denis Palnitsky  · 技术社区  · 14 年前

    我需要从字符串中获取所有子字符串。
    对于EX:

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

    返回2个字符串“aaaaaa”和“ccccc” 假设我们只有一个层次的嵌套。 不确定regexp,但我认为它会很有用。

    6 回复  |  直到 14 年前
        1
  •  32
  •   Jake    14 年前
    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;
    }
    
        2
  •  4
  •   juharr    14 年前

    这里的解决方案不使用正则表达式,也不考虑嵌套。

    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);
        }           
    }
    
        3
  •  2
  •   Mark Byers    14 年前

    可以使用正则表达式,但请记住 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 选项,这样即使文本中有新行,它也会匹配。

        4
  •  2
  •   Nime Cloud Sepideh I    10 年前

    您需要更好地定义控制匹配需求的规则。 当构建任何类型的匹配或搜索代码时,您需要对预期的输入和需要生成的输出进行不同的理解。如果不仔细考虑这些问题,就很容易生成有缺陷的代码。说…

    您应该能够使用正则表达式。 嵌套可能会使其稍微复杂一些,但仍然可行(取决于您希望在嵌套场景中匹配的内容)。比如应该开始:

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

    将上面的代码包装成适合您需要的函数应该很简单。

        5
  •  0
  •   Howie    11 年前

    我很无聊,因此我做了一个无用的微基准测试,它“证明”(在我的数据集上,它有长达7K个字符的字符串,并且 <b> 开始/结束参数的标签)我怀疑 尤哈尔 他的解决方案是三个方案中最快的。

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

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

    注意:编译后的regex在我的数据集中并没有太快的速度。

        6
  •  0
  •   Tomer Wolberg    7 年前

    无regex方法:

    public static List<string> extract_strings(string src, string start, string end)
    {
        if (src.IndexOf(start) > 0)
        {
            src = src.Substring(src.IndexOf(start));
        }
        string[] array1 = src.Split(new[] { start }, StringSplitOptions.None);
        List<string> list = new List<string>();
        foreach (string value in array1)
        {
            if (value.Contains(end))
            {
                list.Add(value.Split(new[] { end }, StringSplitOptions.None)[0]);
            }
        }
        return list;
    }