[英]Optimizing several RegEx in Java Code
下面提到的RegEx在非常大的字符串或超过2000行的情况下表现非常差。 Java字符串基本上由PL / SQL脚本组成。
1-用字符前面和后面的空格替换每次出现的定界字符,例如||,!=或>符号。 这需要无限的时间,并且永远不会结束,因此无法记录时间。
// Delimiting characters for SQLPlus
private static final String[] delimiters = { "\\|\\|", "=>", ":=", "!=", "<>", "<", ">", "\\(", "\\)", "!", ",", "\\+", "-", "=", "\\*", "\\|" };
for (int i = 0; i < delimiters.length; i++) {
script = script.replaceAll(delimiters[i], " " + delimiters[i] + " ");
}
2-以下模式查找所有出现正斜杠/的情况,但前面带有*的除外。 这意味着不要在块注释语法中寻找正斜杠。 对于2000行的String,这大约需要103秒。
Pattern p = Pattern.compile("([^\\*])([\\/])([^\\*])");
Matcher m = p.matcher(script);
while (m.find()) {
script = script.replaceAll(m.group(2), " " + m.group(2) + " ");
}
3-从日期或日期格式中删除所有空格
Pattern p = Pattern.compile("(?i)(\\w{1,2}) +/ +(\\w{1,2}) +/ +(\\w{2,4})");
// Create a matcher with an input string
Matcher m = p.matcher(script);
while (m.find()) {
part1 = script.substring(0, m.start());
part2 = script.substring(m.end());
script = part1 + m.group().replaceAll("[ \t]+", "") + part2;
m = p.matcher(script);
}
有什么方法可以优化所有三个RegEx,以使它们花费的时间更少?
谢谢
阿里
我会回答第一个问题。
您可以将所有这些组合到一个正则表达式替换操作中:
script = script.replaceAll("\\|\\||=>|[:!]=|<>|[<>()!,+=*|-]", " $0 ");
说明:
\|\| # Match ||
| # or
=> # =>
| # or
[:!]= # := or !=
| # or
<> # <>
| # or
[<>()!,+=*|-] # <, >, (, ), !, comma, +, =, *, | or -
当然。 您的第二种方法“几乎”是好的。 问题在于您不使用模式来进行替换。 使用str.replaceAll()
,每次调用此方法时实际上都会创建Pattern
实例。 为您调用了Pattern.compile()
,它花费了90%的时间。
您应该改用Matcher.replaceAll()
。
String script = "dfgafjd;fjfd;jfd;djf;jds\\fdfdf****\\/";
String result = script;
Pattern p = Pattern.compile("[\\*\\/\\\\]"); // write all characters you want to remove here.
Matcher m = p.matcher(script);
if (m.find()) {
result = m.replaceAll("");
}
System.out.println(result);
这不是引起您性能问题的正则表达式,而是您在文本上进行了多次传递并不断创建新的Pattern对象的事实。 正如蒂姆指出的,不仅仅是表现受到损害,而且表现不佳。 当您这样做时,很容易弄乱先前通过的结果。
实际上,我猜想日期中的这些多余空格只是其他替换项的副作用。 如果是这样,您可以通过以下方式一次性完成所有替换操作,而无需添加不需要的字符:
static String doReplace(String input)
{
String regex =
"/\\*[^*]*(?:\\*(?!/)[^*]*)*\\*/|" // a comment
+ "\\b\\d{2}/\\d{2}/\\d{2,4}\\b|" // a date
+ "(/|\\|\\||=>|[:!]=|<>|[<>()!,+=*|-])"; // an operator
Matcher m = Pattern.compile(regex).matcher(input);
StringBuffer sb = new StringBuffer();
while (m.find())
{
// if we found an operator, replace it
if (m.start(1) != -1)
{
m.appendReplacement(sb, " $1 ");
}
}
m.appendTail(sb);
return sb.toString();
}
诀窍是,如果不调用appendReplacement()
,则匹配位置不会更新,就好像没有发生匹配。 因为我忽略了它们,所以注释和日期会与其他不匹配的文本一起重新插入,而且我不必担心匹配其中的斜杠字符。
编辑确保正则表达式的“注释”部分位于“运算符”部分之前。 否则,每个注释的前导/
将被视为运算符。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.