正则表达式找到变量和忽略方法

时间:2011-04-11 13:16:28

标签: java regex

我正在尝试编写一个正则表达式,它在给定的JavaScript代码段中查找所有变量(并且只有变量,完全忽略方法)。实际代码(执行正则表达式的代码)是用Java编写的。

现在,我有这样的事情:

Matcher matcher=Pattern.compile(".*?([a-z]+\\w*?).*?").matcher(string);
while(matcher.find()) {
    System.out.println(matcher.group(1));
}

因此,当“string”的值为variable*func()*20

打印输出是:

variable
func

这不是我想要的。对(的简单否定是行不通的,因为它会使正则表达式捕获不必要的字符或将其删除,但仍会捕获函数。现在,我有以下代码:

Matcher matcher=Pattern.compile(".*?(([a-z]+\\w*)(\\(?)).*?").matcher(formula);
while(matcher.find()) {
    if(matcher.group(3).isEmpty()) {
        System.out.println(matcher.group(2));
    }
}

它有效,打印输出正确,但我不喜欢额外的检查。有任何想法吗?请?

编辑(2011-04-12):

感谢您的所有答案。有问题,为什么我需要这样的东西。你是对的,如果是更大,更复杂的脚本,唯一合理的解决方案就是解析它们。然而,在我的情况下,这将是过度的。我正在研究的JS片段旨在成为简单的公式,类似于(a+b)/2。没有注释,字符串文字,数组等。只有变量和(可能)一些内置函数。我需要变量列表来检查它们是否可以被初始化和这一点(并且完全初始化)。我意识到所有这些都可以使用RPN手动完成(这会更安全),但这些公式将包含更大的脚本并在Web浏览器中进行评估,因此这种方式更方便。

这可能有点脏,但是假设无论谁在编写这些公式(可能是我,大部分时间),都知道正在做什么,并且能够检查它们是否正常工作。

如果有人发现这个问题,想要做类似的事情,现在应该是风险/困难。我这样做,至少我希望如此;)

4 个答案:

答案 0 :(得分:1)

很正确的是,正则表达式无法可靠地用于解析结构化输入。请看这里着名的回复:RegEx match open tags except XHTML self-contained tags

由于任何给定的字符序列可能会或可能不会根据前一个或后续的字符序列改变含义,如果没有lexing 解析输入文本,则无法可靠地识别语法元素。正则表达式可用于前者(将输入流分解为标记),但不能可靠地用于后者(根据标记在流中的位置为标记分配含义)。

答案 1 :(得分:1)

如果你正在重新思考使用正则表达式并想知道你还能做什么,你可以考虑使用AST代替以编程方式访问你的源代码。 This answer表明您可以使用Eclipse Java AST为Java源代码构建语法树。我想你可以为Javascript做类似的事情。

答案 2 :(得分:1)

在这种情况下,正则表达式不会因为Java不规则而削减。您最好的方法是获得一个理解Java语法并构建它的解析器。幸运的是,ANTLRJava 1.6 grammar(和1.5 grammar)。

对于相当有限的用例,您可以轻松扩展变量赋值规则并获取所需的信息。这是一个学习曲线,但对于快速准确的解决方案而言,这可能是您最好的。

答案 3 :(得分:1)

关于正则表达式如何不是考虑工作的最佳工具的所有合理建议非常重要。但是如果你的规则足够简单(并且你知道该规则的局限性),你可能会使用快速而肮脏的正则表达式:

Pattern regex = Pattern.compile(
    "\\b     # word boundary\n" +
    "[A-Za-z]# 1 ASCII letter\n" +
    "\\w*    # 0+ alnums\n" +
    "\\b     # word boundary\n" +
    "(?!     # Lookahead assertion: Make sure there is no...\n" +
    " \\s*   # optional whitespace\n" +
    " \\(    # opening parenthesis\n" +
    ")       # ...at this position in the string", 
    Pattern.COMMENTS);

这匹配标识符,只要它后面没有括号。当然,现在您需要group(0)而不是group(1)。当然,这与许多其他东西(内部字符串,注释等)相匹配......