regex 调整Java堆栈跟踪元素的正则表达式

qnakjoqk  于 12个月前  发布在  Java
关注(0)|答案(1)|浏览(95)

我正在创建一个Java正则表达式,用于匹配Java StackTraceElement的字符串形式。(注意,这 * 不是 * 堆栈跟踪本身的正则表达式。)典型的形式显示在StackTraceElement.toString()中:

  • "com.foo.loader/ [[email protected]](https://stackoverflow.com/cdn-cgi/l/email-protection) /com.foo.Main.run(Main.java:101)"-参见下面的描述[在API文档中]。
  • "com.foo.loader/ [[email protected]](https://stackoverflow.com/cdn-cgi/l/email-protection) /com.foo.Main.run(Main.java)"-行号不可用。
  • "com.foo.loader/ [[email protected]](https://stackoverflow.com/cdn-cgi/l/email-protection) /com.foo.Main.run(Unknown Source)"-文件名和行号都不可用。
  • "com.foo.loader/ [[email protected]](https://stackoverflow.com/cdn-cgi/l/email-protection) /com.foo.Main.run(Native Method)"-包含执行点的方法是本机方法。
  • "com.foo.loader//com.foo.bar.App.run(App.java:12)"-执行点的类在名为com.foo.loader的类加载器的未命名模块中定义。
  • " [[email protected]](https://stackoverflow.com/cdn-cgi/l/email-protection) /org.acme.Lib.test(Lib.java:80)"-执行点的类在acme模块中定义,由内置的类加载器(如应用程序类加载器)加载。
  • "MyClass.mash(MyClass.java:9)"-MyClass类位于应用程序类路径上。

我需要能够访问每个组件作为一个组中产生的匹配器。
目前我有以下正则表达式(为了可读性,Java字符串没有转义):
(?:([^@/]+)/)?(?:(?:([^@/]+)@([\d.+-]+))?/)?([^(]+)\.([^.(]+)\(([^:)]+)(?::(\d+))??\)
在Java代码中:

public static final Pattern ELEMENT_PATTERN = Pattern.compile("(?:([^@/]+)/)?"
    + "(?:(?:([^@/]+)@([\\d.+-]+))?/)?" //optional module name/module version, followed by slash
    + "([^(]+)" //declaring class is always required
    + "\\.([^.(]+)" //method name is always required
    + "\\(([^:)]+)(?::(\\d+))??\\)"); //"file name" (always present in some form, but not necessarily the actual filename) and optional line number

字符串
有两个小小的缺点。这些都不是什么大问题,但如果能解决它们就好了。
1.这个正则表达式将允许"/com.foo.bar.App.run(App.java:12)",我认为这应该被禁止。允许“前两个组件中的一个或两个,但如果存在任何一个,则只允许尾随斜杠”似乎有点复杂。
1.我相信([^(]+)\.([^.(]+)部分需要回溯,因为第一部分首先会消耗方法名。我怀疑这是不是太低效了,但如果有更好的方法,我也不会感到惊讶。
我提出的正则表达式可能已经足够好了,但是正则表达式Maven知道如何解决我提到的这两个问题吗?

ccgok5k5

ccgok5k51#

这是我的想法。我做的最重要的调整是模块版本不一定是数字。事实上,specification并没有以任何方式限制字符,包括斜杠的使用。我试着给模块分配一个包含/的版本,它被接受了。

private static final String ID =
    "\\p{javaJavaIdentifierStart}\\p{javaJavaIdentifierPart}*";

private static final String NAME = ID + "(?:\\." + ID + ")*";

private static final String MODULE = "(" + NAME + ")(?:@(.+))?/";

/**
 * Groups:
 * <ul>
 * <li>1: classloader name
 * <li>2: module name, if loaded from custom classloader
 * <li>3: module version, if loaded from custom classloader
 * <li>4: module name, if NOT loaded from custom classloader
 * <li>5: module version, if NOT loaded from custom classloader
 * <li>6: class name
 * <li>7: method name
 * <li>8: source file
 * <li>9: line number
 * <li>10: text when line number unknown
 * </ul>
 *
 * Only class name and method name are guaranteed to be present;
 * everything else is optional.
 */
private static final Pattern STACK_TRACE_ELEMENT_PATTERN = Pattern.compile(
    "\\bat\\s+"
    + "(?:(" + NAME + ")/(?:/|" + MODULE + ")|" + MODULE + ")?"
    + "(" + NAME + ")\\.(" + ID + ")\\((?:"
        + "(" + ID + "\\.java)(?::(\\d+))?"
        + "|([^)]*)"
        + ")\\)");

字符串

相关问题