我必须处理一个大文件(几 MB)并从中删除带有时间标记的注释。一个例子:
blablabla 12:10:40 I want to remove this
blablabla some more
even more bla
过滤后,我希望它看起来像这样:
blablabla
blablabla some more
even more bla
最好的方法应该是简化正则表达式:
Dataout = Regex.Replace(Datain, "[012][0123456789]:[012345][0123456789]:[012345][0123456789].*", string.Empty, RegexOptions.Compiled);
现在这非常适合我的目的,但它有点慢..我假设这是因为前两个字符 [012] 和 [0123456789] 与很多数据匹配(它是一个包含十六进制的 ASCII 文件数据,例如“0045ab0123”等)。所以 Regex 经常匹配前两个字符。
当我将正则表达式更改为
Dataout = Regex.Replace(Datain, ":[012345][0123456789]:[012345][0123456789].*", string.Empty, RegexOptions.Compiled);
它获得了巨大的加速,可能是因为文件中根本没有很多“:”。好的!但我仍然需要检查第一个“:”之前的两个字符是否为数字,然后删除该行的其余部分。
所以我的问题归结为:
- 如何让 Regex 首先搜索出现次数最少的“:”,并且仅在找到匹配项后才检查之前的两个字符?
或者也许还有更好的方法?
最佳答案
您可以在问题中同时使用这两个正则表达式。首先与前导冒号表达式匹配,以快速查找或排除可能的行。如果成功,则使用完整的替换表达式。
MatchCollection mc = Regex.Matches(Datain, ":[012345][0123456789]:[012345][0123456789].*"));
if ( mc != null && mc.Length > 0 )
{
Dataout = Regex.Replace(Datain, "[012][0123456789]:[012345][0123456789]:[012345][0123456789].*", string.Empty, RegexOptions.Compiled);
}
else
{
Dataout = Datain;
}
一个变体可能是
Regex finder = new Regex(":[012345][0123456789]:[012345][0123456789].*");
Regex changer = new regex("[012][0123456789]:[012345][0123456789]:[012345][0123456789].*");
if ( finder.Match(Datain).Success)
{
Dataout = changer.Replace(Datain, string.Empty);
}
else
{
Dataout = Datain;
}
另一种变体是使用上面的 finder
。如果找到该字符串,则只需检查前两个字符是否为数字即可。
Regex finder = new Regex(":[012345][0123456789]:[012345][0123456789].*");
Match m = finder.Match(Datain);
if ( m.Success && m.Index > 1)
{
if ( char.IsDigit(DataIn[m.index-1]) && char.IsDigit(DataIn[m.index-2])
{
Dataout = m.Index-2 == 0 ? string.Empty : DataIn.Substring(0, m.Index-2);
}
else
{
Dataout = Datain;
}
}
else
{
Dataout = Datain;
}
在第二个和第三个想法中,finder
和changer
应该在读取任何行之前声明并赋值。无需在行读取循环内执行 new Regex(...)
。
关于c# - 搜索时间时正则表达式性能不佳 (xx :xx:xx),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23349640/