我正在尝试制作一个词法分析器。我正在使用 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/