gpt4 book ai didi

Java Pattern 导致堆栈溢出

转载 作者:搜寻专家 更新时间:2023-10-31 20:22:06 24 4
gpt4 key购买 nike

我正在使用正则表达式从任意长的输入字符串中提取键值对,并且遇到了这样一种情况,对于具有重复模式的长字符串,它会导致堆栈溢出。

KV 解析代码看起来像这样:

public static void parse(String input)
{
String KV_REGEX = "((?:\"[^\"^ ]*\"|[^=,^ ])*) *= *((?:\"[^\"]*\"|[^=,^\\)^ ])*)";
Pattern KV_PATTERN = Pattern.compile(KV_REGEX);

Matcher matcher = KV_PATTERN.matcher(input);

System.out.println("\nMatcher groups discovered:");

while (matcher.find())
{
System.out.println(matcher.group(1) + ", " + matcher.group(2));
}
}

一些虚构的输出示例:

    String input1 = "2012-08-09 09:10:25,521 INFO com.a.package.SomeClass - Everything working fine {name=CentOS, family=Linux, category=OS, version=2.6.x}";
String input2 = "2012-08-09 blah blah 09:12:38,462 Log for the main thread, PID=5872, version=\"7.1.8.x\", build=1234567, other=done";

调用 parse(input1) 产生:

{name, CentOS
family, Linux
category, OS
version, 2.6.x}

调用 parse(input2) 产生:

PID, 5872
version, "7.1.8.x"
build, 1234567
other, done

这很好(即使第一种情况需要一些字符串处理)。但是,当尝试解析一个很长(超过 1,000 个字符)的类路径字符串时,会发生上述类溢出,并出现以下异常(开始):

Exception in thread "main" java.lang.StackOverflowError
at java.util.regex.Pattern$BitClass.isSatisfiedBy(Pattern.java:2927)
at java.util.regex.Pattern$8.isSatisfiedBy(Pattern.java:4783)
at java.util.regex.Pattern$8.isSatisfiedBy(Pattern.java:4783)
at java.util.regex.Pattern$8.isSatisfiedBy(Pattern.java:4783)
at java.util.regex.Pattern$8.isSatisfiedBy(Pattern.java:4783)
at java.util.regex.Pattern$CharProperty.match(Pattern.java:3345)
...

字符串太长,无法放在这里,但它具有以下易于重现和重复的结构:

java.class.path=/opt/files/any:/opt/files/any:/opt/files/any:/opt/files/any

任何想要重现该问题的人只需将 :/opt/files/any 附加到上述字符串中几十次即可。在类路径字符串中创建包含大约 90 个 ":/opt/files/any"副本的字符串后,发生堆栈溢出。

是否有一种通用的方法可以修改上述 KV_REGEX 字符串,从而不会出现问题并产生相同的结果?

我明确地将泛型放在上面,而不是(例如)在解析之前检查最大字符串长度的 hack。

我能想出的最粗略的修复,一个真正的反模式,是

public void safeParse(String input)
{
try
{
parse(input);
}
catch (StackOverflowError e) // Or even Throwable!
{
parse(input.substring(0, MAX_LENGTH));
}
}

有趣的是,它在我试过几次后运行良好,但它的品位还不够值得推荐。 :-)

最佳答案

您的正则表达式看起来过于复杂,例如我认为您还不太了解字符类的工作原理。这对我来说效果更好,我不能让它溢出了:

public static void parse(String input) {
String KV_REGEX = "(\"[^\" ]*\"|[^{=, ]*) *= *(\"[^\"]*\"|[^=,) }]*)";
Pattern KV_PATTERN = Pattern.compile(KV_REGEX);

Matcher matcher = KV_PATTERN.matcher(input);

System.out.println("\nMatcher groups discovered:");

while (matcher.find()) {
System.out.println(matcher.group(1) + ", " + matcher.group(2));
}
}

要分解正则表达式,这将匹配:

(\"[^\"]*\"|[^{=, ]*):任何包含在 " 中的内容,或任意数量的非{=, 个字符

*= *:零到任意个空格,后面跟=,后面跟零到任意个空格

(\"[^\"]*\"|[^=,) }]*):任何包含在 " 中的内容,或任意数量的非-=,) } 个字符

关于Java Pattern 导致堆栈溢出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11891402/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com