java - 在 Java 中使用 Matcher 和 Pattern 对象时出现问题

标签 java regex posix

我正在尝试制作一个词法分析器。我正在使用 Matcher 对象从 HTML 字符串获取下一个标记。我正在尝试使用 Matcher 的lookingAt() 方法来获取我正在查找的 POSIX 表达式的第一次出现。问题是 group() 应该只打印出与表达式匹配的短语,但它却打印出整个 HTML 字符串。这是代码:

public static final String[] DEFAULT_RULES = new String[] {         
            // PUT YOUR REGULAR EXPRESSIONS HERE.  SEE THE ORDER BELOW
            "<!--.*-->",                                    // A comment TESTED
            "<\\p{Alnum}+.*\\p{Blank}*/>",                  // Singular Tag
            "<\\p{Alnum}+.*[^/]*>",                         // Opening Tag TESTED
            "</\\p{Alnum}+\\p{Space}*>",                    // Closing Tag TESTED
            "&.*;",                                         // HTTP Entity TESTED
            ".*"    };

方法:

    for( int i = 0; i < DEFAULT_RULES.length; i++ ) {// Loop through each expression and try to find a matching phrase
        pattern = Pattern.compile( DEFAULT_RULES[i], Pattern.DOTALL );  // Get a Regex Pattern
        matcher = pattern.matcher( mainString );    // Check if Pattern matches the String

        //matcher.region( position, mainString.length() );  // Make the Region start from the current pointer to the end

        if( matcher.lookingAt() ) {     // Match found at current position
            int s = matcher.start();
            int e = matcher.end();
            String nextToken = matcher.group();     // Save the current phrase that matched the expression
            position = matcher.end();           // Move position pointer to the character after the end of the Token
            return nextToken;// return the Token
        }
    }

注意: DEFAULT_RULES 是我正在查找的表达式字符串列表。我期望的输出是:

<P>

但是我得到了整个 HTML 文件。我希望这是有道理的。

最佳答案

lookingAt()应用正则表达式,就好像它在开头锚定为 \A ,因此您将获得的唯一匹配是从主题的一开始开始的匹配。如果主题不是以 < 开头或& ,该列表中唯一匹配的正则表达式是最后一个,.* 。而且,由于您在 DOTALL 模式下进行匹配,因此 .*将始终匹配整个主题。

看起来您打算在每场比赛后更新比赛开始位置,并且我看到您正在保存新位置,但您从未对其进行任何操作。您需要在 region(int, int) 中使用它方法来更改匹配器认为的主题开头,如下所示:

position = matcher.end();
matcher.region(position, matcher.regionEnd());

但是,由于 .*,每场比赛你仍然会得到比你想要的更多的东西。在大多数正则表达式中,所有这些正则表达式都以 DOTALL 模式应用。你需要比这更具体。具体程度取决于您的最终目标是什么。如果您正在尝试为完整的、工业强度的 HTML 解析器编写词法分析器,那么您应该立即放弃它并阅读真正的解析器是如何编写的。

Here's来自 Mastering Regular Expressions 的代码列表这与你正在做的类似。它演示了一些重要的技术,例如将正则表达式保存为已编译的 Pattern 对象,并使用 Matcher 的 usePattern() 交换它们。方法而不是不断创建新的 Pattern 和 Matcher 对象。 (他还在每个正则表达式中添加 \\G 并使用 find()find(int) 来应用它们;该部分已经过时了。region()lookingAt() 就是您所需要的。)

关于java - 在 Java 中使用 Matcher 和 Pattern 对象时出现问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4403995/

相关文章:

java - Spring MVC 3 获取初始化参数

java ;字符串替换(使用正则表达式)?

c - Linux 是否允许将进程组 ID 重新分配给进程?

linux - 语言环境如何在 Linux/POSIX 中工作以及应用了哪些转换?

c - errno 11 [EAGAIN] 来自 read(2)

java - 如何使用 Scanner 处理无效输入(InputMismatchException)引起的无限循环

java - C#中的对称加密类似于JAVA

java - 使用带有 ajax 请求的表单调用 Servlet (FIlter)(必须使用授权 header )

Java正则表达式拆分文本(分隔符和顺序都可能未知)

python - pypeg2 - 可以使用 peg 语法解析此表达式吗?