Java代码中几个正则表达式的优化

Java代码中几个正则表达式的优化,java,regex,optimization,Java,Regex,Optimization,下面提到的正则表达式在非常大的字符串或超过2000行上的性能非常差。Java字符串基本上由PL/SQL脚本组成 1-替换每个出现的定界字符,例如| |,!=或>在字符前后用空格签名。这需要无限的时间,永远不会结束,所以没有时间可以记录 // Delimiting characters for SQLPlus private static final String[] delimiters = { "\\|\\|", "=>", ":=", "!=", "<>", "<",

下面提到的正则表达式在非常大的字符串或超过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] + " ");
}
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);
}
有没有办法优化所有三个正则表达式,以减少它们所需的时间

谢谢


阿里

我来回答第一个问题

您可以将所有这些合并到单个正则表达式替换操作中:

script = script.replaceAll("\\|\\||=>|[:!]=|<>|[<>()!,+=*|-]", " $0 ");
script=script.replaceAll(“\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\;
说明:

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

造成性能问题的不是正则表达式,而是您对文本进行了多次传递,并不断创建新的模式对象。正如蒂姆所指出的,不仅仅是表现不佳;当你这么做的时候,很容易把之前的传球结果搞砸

事实上,我猜日期中那些额外的空格只是其他替代品的副作用。如果是这样,您可以在一次过程中完成所有替换,而不添加不需要的字符:

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();
}
静态字符串数据替换(字符串输入)
{
字符串正则表达式=
“//\\*[^*]*(?:\\*(?!/)[^*]*)*\\*/\”//注释
+“\\b\\d{2}/\\d{2}/\\d{2,4}\\b|”//日期
+“(//\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
Matcher m=Pattern.compile(regex).Matcher(input);
StringBuffer sb=新的StringBuffer();
while(m.find())
{
//如果我们找到了操作员,请更换它
如果(m.开始(1)!=-1)
{
m、 (sb,“$1”);
}
}
m、 (某人);
使某人返回字符串();
}

诀窍是,如果不调用
appendReplacement()
,匹配位置不会更新,因此就好像匹配没有发生一样。因为我忽略了它们,注释和日期会与其他不匹配的文本一起重新插入,我不必担心匹配其中的斜杠字符


编辑确保正则表达式的“注释”部分位于“运算符”部分之前。否则,每条注释的前导
/
将被视为运算符。

您应该将此问题分成三个独立的问题。这也将有助于您创建比“优化多个正则表达式”更有意义(因此也更有趣)的问题标题……但这会更快吗?“我怀疑。”艾德夫:我很肯定会的。最初的解决方案是将其转换成
a:=b | c
,然后转换成
a:=b | c
,然后转换成
a:=b | c
,然后转换成
a:=b | c
,然后转换成
a:=b | c
(我只展示了实际发生事情的步骤,我肯定他并不打算这样做). 这里没有显示大量由此引入的双空格,但您了解了总体思路。
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();
}