我正在尝试制作一个Lexer。我正在使用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文件。我希望这是有道理的。
答案 0 :(得分:1)
组索引0始终是整个匹配字符串。索引1+返回各个组。所以
字符串:abc
正则表达式:。*(b)。*
第0组:abc
第1组:b
答案 1 :(得分:1)
您的正则表达式可能与整个文档匹配,而不仅仅是<P>
标记。这可能是由于贪婪的匹配。如果你正在使用这样的东西:
<P.*>
你可能最好按照
的方式修改它<P.*?>
或
<P[^>]*>
请参阅此页面上的“不情愿的量词”部分:http://download.oracle.com/javase/1.4.2/docs/api/java/util/regex/Pattern.html
答案 2 :(得分:1)
lookingAt()
将正则表达式应用为\A
的开头,因此您将获得的唯一匹配就是从主题的开头开始的匹配。如果主题不是<
或&
,则该列表中唯一匹配的正则表达式是最后一个.*
。而且,由于您在DOTALL模式下进行匹配,.*
将始终与整个主题匹配。
看起来你打算在每场比赛后更新比赛开始位置,我看到你保存新位置,但你从不做任何事情。您需要在region(int, int)
方法中使用它来更改Matcher认为的主题的开头,如下所示:
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()
就是您所需要的。)