gpt4 book ai didi

java - 使用正则表达式解析文本文件

转载 作者:行者123 更新时间:2023-12-01 18:52:36 24 4
gpt4 key购买 nike

我正在尝试使用正则表达式通过提取某些文本片段来解析文件。标准 java.util.regex 包不支持我需要使用的正则表达式(因为我需要匹配嵌套构造,例如嵌套 {} 括号和其他类似的事情),所以我决定尝试JRegex ,它声称可以完全处理 Perl 5.6 正则表达式语法。但是,当我尝试将此包与递归正则表达式一起使用以匹配嵌套的 {} 括号时遇到了问题:

Pattern p = new Pattern("(\\{(?:(?1)*|[^{}]*)+\\}|\\w+)");  // jregex.Pattern
Exception in thread "main" jregex.PatternSyntaxException: wrong char after "(?": 1

类似的正则表达式 /(\{(?:(?1)*|[^{}]+)+\}|\w+)/sg 在 Perl 中按预期工作。因此,我的下一个想法是找到一种方法在 Perl 中解析文件,然后将结果传递给 Java(最好以字符串数组或类似的形式) ,我的问题是:在这种情况下最好的方法是什么?或者,还有我忽略的另一种更简单的选择吗?

最佳答案

JRegex 似乎不支持递归匹配,所以我建议你只使用 java.util.regex 并设置嵌套层数的限制。

例如,要允许最多五十层嵌套,并且每层上的括号对数量“无限”(最深的除外),您可以使用

// Set the maximum number of nested levels required.
int max = 50;
String regex = "(?R)";

while (--max > 0) {
regex = regex.replace("(?R)", "(?>\\{(?:[^{}]*+|(?R))+\\})");
}

// Ensure no (?R) in the final and deepest replacement.
regex = regex.replace("(?R)", "\\{[^{}]*+\\}") + "|\\w+";

String str = " {{}{}} {abc} {{de}{fg}} hij {1{2{3{4{5{6{7{8{9{10{11{12{13{14{15{16{17{18{19{20{21{22{23{24{25{26{27{28{29{30{31{32{33{34{35{36{37{38{39{40{41{42{43{44{45{46{47{48{49{50}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}} {end}";
Matcher m = Pattern.compile(regex).matcher(str);

while (m.find()) {
System.out.println(m.group());
}

/*
{{}{}}
{abc}
{{de}{fg}}
hij
{1{2{3{4{5{6{7{8{9{10{11{12{13{14{15{16{17{18{19{20{21{22{23{24{25{26{27{28{29{30{31{32{33{34{35{36{37{38{39{40{41{42{43{44{45{46{47{48{49{50}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}
{end}
*/

上面通过采用支持递归匹配时可以使用的正则表达式来构建正则表达式 (?>\\{(?:[^{}]*+|(?R))+\\} ) 并重复用 (?R) 替换整个模式。

由于创建的表达式中有很多嵌套量词,因此使用原子分组(?>)和所有格量词+来限制回溯并确保如果正则表达式找不到匹配项,它会很快失败。尽管正则表达式可能很长,但它会很有效。

如果您不想或无法对嵌套设置限制,或者如果冗长的正则表达式的想法令人担忧,您可以通过简单地迭代文件文本并跟踪打开的次数来解析嵌套括号和右括号,例如

List<String> list = new ArrayList<String>();
int strLen = str.length();

for (int i = 0; i < strLen; i++) {
char c = str.charAt(i);

if (c == '{') {
int b = 1;
StringBuilder sb = new StringBuilder("{");

while (b > 0 && i < strLen - 1) {
sb.append( c = str.charAt(++i) );

if (c == '}') b--;
else if (c == '{') b++;
}
list.add(sb.toString());
}
}

for (String s : list) { System.out.println(s); }

这似乎比与 Perl 交互要少很多麻烦,但请参阅诸如 How should I call a Perl Script in Java? 之类的答案。如果这就是您想要做的。

关于java - 使用正则表达式解析文本文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15310929/

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