长命名捕获组正则表达式模式的问题
Problem with long named capturing groups regex patterns
我已经创建并初步验证了以下正则表达式。它旨在成为分词器的一部分,在将某些模式传递给解析器之前对其进行识别和分组。
(?<FUNCTION> (?!CUP\(\d+\)|CDN\(\d+\))[A-Z]+\(\d*\)|[A-Z]+\(\d+,\d+\))
| (?<NUMBER>\d+|\d*\.\d+)
| (?<RELATION>==|<=|>=|!=|<|>|CUP\(\d+\)|CDN\(\d+\))
| (?<EOL>;)
| (?<OPENPAR>\()
| (?<CLOSEPAR>\))
| (?<OPERATION>\*|\+|-|\/])
| (?<SPACE>\s+)
| (?<ERROR>.)
通过以上内容,使用正则表达式引擎属性以及降低子模式的复杂性,我能够正确地捕获所有组。下面的示例文本按预期匹配,捕获命名捕获组中的正确部分(在 regex101 上:https://regex101.com/r/nvRyjt/2)。到目前为止一切顺利。
TICK()<=.(2*STDEVEMA(14))+EMA(14);
TREND(14,2)==UP(2);
TICK()>EMA(14);
TREND(14)==UP(1);
EMA(14)CUP(2)EMA(28);
EMA(14)CDN(2)EMA(28)
2*3==6;
ssst2222 \\///???
sfgjsf
当我尝试在 java.util.regex 中使用此表达式时出现问题。对于较小的组,模式只捕获很少的出现,并且输入文本的剩余可识别部分被跳过或显示为 'nulls'。我尝试了很多组合,包括将模式限制为两个或三个组,但对于导致意外行为的原因没有明确的结论。通过搜索到目前为止发布的问题,我清楚地注意到 regex101(和一般的 PCRE)不是验证稍后在 java :-) 中使用的正则表达式的好工具。发帖时我想问以下问题:
- 你们中有人知道有关 Pattern 和 Matcher 类 工作原理(尤其是正则表达式引擎)的任何深入描述吗?
- 您是否遇到过类似的复杂正则表达式模式的问题(也许 java.util 有某些不那么明显的限制)?
还有一个更具体的事情,具有负面的前瞻性。像这样构造:
(?<FUNCTION> (?!CUP\(\d+\)|CDN\(\d+\))[A-Z]+\(\d*\)|[A-Z]+\(\d+,\d+\))
仅跳过第一个字符 'C' 表示关键字的剩余部分(CUP 或 CDN)有效(在本例中为 UP 或 DN)。对此有什么想法吗?
提前致谢!
我不确定我是否能回答你的问题,但你可以试试下面的方法。
使用 regex101 站点上的代码生成器工具(在工具下方的左侧)并使用 java 作为您的语言。
从生成的正则表达式字符串中删除 \n
。不删除它可能会导致您的问题?!
package com.company;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Main {
public static void main(String[] args) {
final String regex = "(?<FUNCTION> (?!CUP\(\d+\)|CDN\(\d+\))[A-Z]+\(\d*\)|[A-Z]+\(\d+,\d+\))" +
" | (?<NUMBER>\d+|\d*\.\d+)" +
" | (?<RELATION>==|<=|>=|!=|<|>|CUP\(\d+\)|CDN\(\d+\))" +
" | (?<EOL>;)" +
" | (?<OPENPAR>\()" +
" | (?<CLOSEPAR>\))" +
" | (?<OPERATION>\*|\+|-|\/])" +
" | (?<SPACE>\s+)" +
" | (?<ERROR>.)";
final String string = "TICK()<=.(2*STDEVEMA(14))+EMA(14);\n"
+ "TREND(14,2)==UP(2);\n"
+ "TICK()>EMA(14);\n"
+ "TREND(14)==UP(1);\n"
+ "EMA(14)CUP(2)EMA(28);\n"
+ "EMA(14)CDN(2)EMA(28)\n"
+ "2*3==6;\n"
+ "ssst2222 \\\\///???\n"
+ "sfgjsf\n";
final Pattern pattern = Pattern.compile(regex, Pattern.MULTILINE | Pattern.COMMENTS);
final Matcher matcher = pattern.matcher(string);
while (matcher.find()) {
System.out.println("Full match: " + matcher.group(0));
for (int i = 1; i <= matcher.groupCount(); i++) {
System.out.println("Group " + i + ": " + matcher.group(i));
}
}
}
}
注意
我得到了 67 个匹配项,regex101 得到了 89 个匹配项。
这是因为 SPACE 在 regex101 中的 ERROR 之前匹配。在 Java 中不是。可能是 regex101 支持的扩展模式,在 Java.
中似乎不可用
示例:
final String string = "TICK()<=."
在Java中给出:
Full match: TICK()
Full match: <=
Full match: .
在 regex101 中给出:
Match 1 Full match 0-6 TICK()
Match 2 Full match 6-8 <=
Match 3 Full match 8-8
Match 4 Full match 8-9 .
我已经创建并初步验证了以下正则表达式。它旨在成为分词器的一部分,在将某些模式传递给解析器之前对其进行识别和分组。
(?<FUNCTION> (?!CUP\(\d+\)|CDN\(\d+\))[A-Z]+\(\d*\)|[A-Z]+\(\d+,\d+\))
| (?<NUMBER>\d+|\d*\.\d+)
| (?<RELATION>==|<=|>=|!=|<|>|CUP\(\d+\)|CDN\(\d+\))
| (?<EOL>;)
| (?<OPENPAR>\()
| (?<CLOSEPAR>\))
| (?<OPERATION>\*|\+|-|\/])
| (?<SPACE>\s+)
| (?<ERROR>.)
通过以上内容,使用正则表达式引擎属性以及降低子模式的复杂性,我能够正确地捕获所有组。下面的示例文本按预期匹配,捕获命名捕获组中的正确部分(在 regex101 上:https://regex101.com/r/nvRyjt/2)。到目前为止一切顺利。
TICK()<=.(2*STDEVEMA(14))+EMA(14);
TREND(14,2)==UP(2);
TICK()>EMA(14);
TREND(14)==UP(1);
EMA(14)CUP(2)EMA(28);
EMA(14)CDN(2)EMA(28)
2*3==6;
ssst2222 \\///???
sfgjsf
当我尝试在 java.util.regex 中使用此表达式时出现问题。对于较小的组,模式只捕获很少的出现,并且输入文本的剩余可识别部分被跳过或显示为 'nulls'。我尝试了很多组合,包括将模式限制为两个或三个组,但对于导致意外行为的原因没有明确的结论。通过搜索到目前为止发布的问题,我清楚地注意到 regex101(和一般的 PCRE)不是验证稍后在 java :-) 中使用的正则表达式的好工具。发帖时我想问以下问题:
- 你们中有人知道有关 Pattern 和 Matcher 类 工作原理(尤其是正则表达式引擎)的任何深入描述吗?
- 您是否遇到过类似的复杂正则表达式模式的问题(也许 java.util 有某些不那么明显的限制)?
还有一个更具体的事情,具有负面的前瞻性。像这样构造:
(?<FUNCTION> (?!CUP\(\d+\)|CDN\(\d+\))[A-Z]+\(\d*\)|[A-Z]+\(\d+,\d+\))
仅跳过第一个字符 'C' 表示关键字的剩余部分(CUP 或 CDN)有效(在本例中为 UP 或 DN)。对此有什么想法吗? 提前致谢!
我不确定我是否能回答你的问题,但你可以试试下面的方法。
使用 regex101 站点上的代码生成器工具(在工具下方的左侧)并使用 java 作为您的语言。
从生成的正则表达式字符串中删除 \n
。不删除它可能会导致您的问题?!
package com.company;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Main {
public static void main(String[] args) {
final String regex = "(?<FUNCTION> (?!CUP\(\d+\)|CDN\(\d+\))[A-Z]+\(\d*\)|[A-Z]+\(\d+,\d+\))" +
" | (?<NUMBER>\d+|\d*\.\d+)" +
" | (?<RELATION>==|<=|>=|!=|<|>|CUP\(\d+\)|CDN\(\d+\))" +
" | (?<EOL>;)" +
" | (?<OPENPAR>\()" +
" | (?<CLOSEPAR>\))" +
" | (?<OPERATION>\*|\+|-|\/])" +
" | (?<SPACE>\s+)" +
" | (?<ERROR>.)";
final String string = "TICK()<=.(2*STDEVEMA(14))+EMA(14);\n"
+ "TREND(14,2)==UP(2);\n"
+ "TICK()>EMA(14);\n"
+ "TREND(14)==UP(1);\n"
+ "EMA(14)CUP(2)EMA(28);\n"
+ "EMA(14)CDN(2)EMA(28)\n"
+ "2*3==6;\n"
+ "ssst2222 \\\\///???\n"
+ "sfgjsf\n";
final Pattern pattern = Pattern.compile(regex, Pattern.MULTILINE | Pattern.COMMENTS);
final Matcher matcher = pattern.matcher(string);
while (matcher.find()) {
System.out.println("Full match: " + matcher.group(0));
for (int i = 1; i <= matcher.groupCount(); i++) {
System.out.println("Group " + i + ": " + matcher.group(i));
}
}
}
}
注意
我得到了 67 个匹配项,regex101 得到了 89 个匹配项。
这是因为 SPACE 在 regex101 中的 ERROR 之前匹配。在 Java 中不是。可能是 regex101 支持的扩展模式,在 Java.
中似乎不可用示例:
final String string = "TICK()<=."
在Java中给出:
Full match: TICK()
Full match: <=
Full match: .
在 regex101 中给出:
Match 1 Full match 0-6 TICK()
Match 2 Full match 6-8 <=
Match 3 Full match 8-8
Match 4 Full match 8-9 .