我需要从字符串中获取所有的子字符串。
例如:
StringParser.GetSubstrings("[start]aaaaaa[end] wwwww [start]cccccc[end]", "[start]", "[end]");
假设我们只有一层嵌套,要返回两个字符串 "aaaaaa" 和 "cccccc"。我不确定是否需要使用正则表达式,但我认为它可能会有用。
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;
}
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);
}
}
你需要更好地定义规则来管理你的匹配需求。 当构建任何类型的匹配或搜索代码时,你需要非常清楚你预期的输入和需要产生的输出。如果你不认真考虑这些问题,很容易产生错误的代码。话虽如此...
你应该能够使用正则表达式。 嵌套可能会使它稍微复杂一些,但仍然可以做到(取决于你在嵌套情况下希望匹配什么)。像这样的东西应该能够让你入门:
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 );
将上面的代码封装成符合您需求的函数应该很简单。
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);
}
我感到无聊,于是我做了一个毫无用处的微型基准测试。在我的数据集中,字符串长度最长可达7k个字符,还有<b>
标签作为起始/结束参数。这"证明"了我的猜想,即juharr的解决方案是三种方案中整体最快的。
结果(1000000次迭代*20个测试用例):
juharr: 6371ms
Jake: 6825ms
Mark Byers: 82063ms
注意:在我的数据集上编译的正则表达式并没有提高速度。
[start]xxx[start]yyy[end]zzz[end]
是可能的吗? - kennytm