检查各个捕获组

时间:2013-03-07 13:45:24

标签: java regex http

我有一个HTTP请求,我已经构建了一个表达式。到目前为止,表达式有效,我可以将请求拆分为一个字符串数组,但我想看看是否可以通过匹配各个捕获组来简化它。

所以:

private void process(final String message) {
     Pattern pattern = Pattern.compile("(GET|get){1}\\s(/.*)\\s(HTTP|http)(/1\\.0)");
     Matcher matcher = pattern.matcher(message);    
}

请求是这样的:

GET / HTTP/1.0

很简单。那么,有什么方法可以通过每个捕获组来检查是否匹配?假设请求有POST而不是GET,是否可以检查第一个捕获组然后返回501“未实现”响应?

我的第一个解决方案是简单地用空格分割消息,然后检查每个单独的数组元素。但这似乎有点“糟糕”。

修改

问题是,matches()匹配整个事物,如果一个组失败,那么整个表达式就会失败,这是我不想要的。任何数量的组都应该可以失败/成功,而不会抛出IllegalStateException。

2 个答案:

答案 0 :(得分:1)

即使在某些群体不相同的情况下仍然匹配,他们需要是可选的。

然后使用Matcher#find()方法和Matcher#group(x)来访问组(从1开始,因为0是整个匹配)。

示例:

String msg = "GET HTTP 200 OK"; //resource and protocol version are left out by purpose

Pattern pattern = Pattern.compile("(GET|get)?\\s(/[^\\s]*)?\\s(HTTP|http)?(/1\\.0)?");
Matcher matcher = pattern.matcher( msg );

while ( matcher.find() )
{
  System.out.println(matcher.group( 1 ));  //prints GET
  System.out.println(matcher.group( 2 ));  //prints null since there's no resource
  System.out.println(matcher.group( 3 ));  //prints HTTP
  System.out.println(matcher.group( 4 ));  //prints null since there's no version string
}

作为旁注,我需要稍微调整一下你的表达,因为第二组(/.*)会在第一个斜杠之后贪婪地匹配任何东西。尽管如此,它还远非完美。



第二种方法可能是应用多个表达式/模式并将它们一个接一个地应用于匹配器。

示例:

Pattern methodPattern = Pattern.compile("GET|get");
Matcher matcher = methodPattern.matcher( msg );

if ( matcher.find() )
{
  System.out.println("method: " + matcher.group());
}

if ( matcher.usePattern( Pattern.compile("\\s/([^\\s]*)") ).find() )
{
  System.out.println("resource: " + matcher.group(1));
}

if ( matcher.usePattern( Pattern.compile("HTTP|http") ).find() )
{
  System.out.println("protocol: " + matcher.group());
}

if ( matcher.usePattern( Pattern.compile("/(\\d\\.\\d)") ).find() )
{
  System.out.println("version: " + matcher.group(1));
}

这使用以下事实:匹配器的读取位置设置为匹配后的位置,随后对find()的任何调用都将从那里开始。如果模式不匹配,则位置保持不变。

因此,必须按顺序应用模式,但这些模式是可选的。

答案 1 :(得分:0)

您知道在执行matches()后,Matcher还允许您使用group()方法提取特定组的匹配内容吗?但是,您需要调整模式以匹配GET和POST(以及其他任何方法)。一旦你检索到这样的相关字符串,你就可以再次匹配它上面的(nother)模式,或者在各种条件结构之一中使用它......(switch语句现在也适用于String( Java 7)。)

另一种策略是匹配分隔符,并允许任何字符串作为HTTP方法(甚至是垃圾)。然后检查实际的组值。

另一种策略是为每个要分别处理的错误条件设置一个单独的模式,然后查看哪个模式匹配(如果匹配,则适当地处理错误)。但是,通常存在一个未命中的情况,因此并非所有可以想到的错误都得到处理。你真的需要知道你在做什么......

但是,Java确实提供了许多网络库代码,因此您无需进行此类regexp检查。例如,请参阅javax.servlet.http.HttpServletRequest#getMethod() ...