(?s)^\d++\s{1,2}(.{12}) --> (.{12})\s{1,2}(.+)\r?$
我不知道这是否重要,但这是使用Scala编程语言完成的(Java引擎,但使用文字字符串以便我不必双倍反斜杠)。
使用s{1,2}
是因为某些文件仅具有换行符\n
,而其他文件则具有换行符和回车符\n\r
。第一个(?s)
启用DOTALL
模式,以使第三个捕获组也可以匹配换行符。
我的程序基本上使用\n\r?\n
作为分隔符来拆分srt文件,并使用Scala很好的模式匹配功能来读取每个条目以进行进一步处理:
val EntryRegex = """(?s)^\d++\s{1,2}(.{12}) --> (.{12})\s{1,2}(.+)\r?$""".r
def apply(string: String): Entry = string match {
case EntryRegex(start, end, text) => Entry(0, timeFormat.parse(start),
timeFormat.parse(end), text);
}
样例输入:
一行:
1073
01:46:43,024 --> 01:46:45,015
I am your father.
两行:
160
00:20:16,400 --> 00:20:19,312
<i>Help me, Obi-Wan Kenobi.
You're my only hope.</i>
问题在于,分析器显示这种解析方法是我应用程序中耗时最长的操作(该应用程序进行密集的时间数学运算,甚至可以比读取和解析条目所需的时间快几倍重新编码文件)。
那么,有任何正则表达式专家可以帮助我优化吗?或者我应该牺牲正则表达式/模式匹配的简洁性,尝试一种老派的java.util.Scanner
方法?
干杯!
\d++\s{1,2}
在语义上与\d+\s{1,2}
没有任何区别,因为在\d+{1,2}
中没有字符串具有非空后缀,这些后缀是\s{1,2}
中任何字符串的非空前缀,但显然只有基准测试才能确定限定符是否改进了事情。 - Mike Samuel\s\d+\s
这样的回溯可能是毫无意义的,我们可能已经很明显了,但是NFA正则表达式引擎(例如Java的,.NET的,Python的和Perl的)仍然倾向于做好准备,除非我们告诉它们不要这样做。 - Alan Moore