用Java匹配正则表达式组
我正试图通过使用组来拆分一行与regex的代码,但它并没有像我预期的那样工作。用Java匹配正则表达式组,java,regex,string,regex-group,Java,Regex,String,Regex Group,我正试图通过使用组来拆分一行与regex的代码,但它并没有像我预期的那样工作。 例如,我想匹配以下行: 例1:temp name(这是数据) 还有: 例2:temp name() 我使用了这个正则表达式: [\s]*temp[\s]+[\s]*([A-Za-z]+)[\s]*[(]\s*(.*)+[)]\s*[{]\s* 这意味着:抓取以temp开头的任何内容,然后将“名称”放入第1组,然后抓取括号内的任何内容,将其放入第2组 但是,第2组始终为空 这是我获取数据的代码: Pattern PA
例如,我想匹配以下行: 例1:
temp name(这是数据)
还有:
例2:temp name()
我使用了这个正则表达式:
[\s]*temp[\s]+[\s]*([A-Za-z]+)[\s]*[(]\s*(.*)+[)]\s*[{]\s*
这意味着:抓取以temp
开头的任何内容,然后将“名称”放入第1组,然后抓取括号内的任何内容,将其放入第2组
但是,第2组始终为空
这是我获取数据的代码:
Pattern PATTERN = Pattern.compile("[\\s]*temp[\\s]+[\\s]*([A-Za-z]+)[\\s]*[(]\\s*(.*)+[)]\\s*");
Matcher m = PATTERN.matcher("temp name(this is the data)");
m.matches();
String name = m.group(1);
String data = m.group(2); // always empty
我做错了什么?您的模式不匹配,因为它需要在末尾使用一个开放的花括号,但您的输入没有花括号 忽略这个小问题,主要问题是捕获组
(.*)+
之后的小+
。加号需要一个或多个匹配项*
,返回的组是许多匹配项中的最后一个。术语*
是贪婪的,所以它会消耗掉括号内的所有东西。再次匹配的唯一方法是不消耗任何东西。所以第二组的最后一个匹配是空白的
要解决此问题,请删除组2后的+
:
Pattern PATTERN = Pattern.compile("\\s*temp\\s+([A-Za-z]+)\\s*[(]\\s*(.*)[)]\\s*");
还要注意我是如何从正则表达式中删除其他不必要的字符的,例如单字符字符类-即[\\s]
与\s
相同。而\\s+\\s*
与\\s+
完全相同,因为+
是贪婪的
我还删除了尾随的花括号,如果您的输入数据确实有它,您可以恢复它(您的问题显示输入了
“temp name(这是数据)”
,它没有尾随的花括号)。[\s]
与\s
[\s]+[\s]*
等同于\s+
[(]
等同于\(
(与[)]
和[}]
相同)
这将使您的regexp成为:
\s*temp\s+([A-Za-z]+)\s*\(\s*(.*)+\)\s*{\s*
假设您确实想要匹配临时名称(…){
(您的regexp正在查找{
,而在您的问题中您没有指定):
(.*)+
是您的问题。您的意思是:“匹配任意数量(包括0个)的聊天参与者,并将其放入捕获组,至少重复一次”
默认情况下,Regexp是贪婪的(=它们消耗尽可能多),因此捕获组将首先包含两个括号内的所有内容,然后+
将再次尝试匹配整个组,并将其与“
(emtpy字符串)匹配因为这符合捕获组的模式。这将延长捕获组的有效期
您想要的是
\s*temp\s+([A-Za-z]+)\s*(\s*(.*)\)\s*{\s*
您的正则表达式应该是:
Pattern pattern = Pattern.compile("\\s*temp\\s+([A-Za-z]+)\\s*[(]\\s*(.*)[)]\\s*");
您有(.*)+
,这意味着一个或多个*
匹配项。这将导致未捕获任何内容
测试:
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Example {
public static void main(String[] args) {
Pattern pattern = Pattern.compile("\\s*temp\\s+([A-Za-z]+)\\s*[(]\\s*(.*)[)]\\s*");
Matcher m = pattern.matcher("temp name(this is the data)");
if(m.matches()) {
System.out.println(m.group(1));
System.out.println(m.group(2));
}
}
}
输出:
name
this is the data
获取空组的原因是,每次在()之间放置某个内容时,即使它是嵌套的,也会创建多个捕获组 要使一个组不被捕获,您可以使用?:例如
(?:sometest(这是我们想要的值))
将只返回一个组,而(sometest(这是我们想要的值))
将返回两个组
对于您特定的正则表达式,我已经对其进行了改进和简化,因为您有不需要的捕获组
简单解决方案:
\\s*temp\\s+([A-Za-z]+)\\s*\\(\\s*(.*)\\\\\\s*\{\\s*
根据输入:
Ex. #1: temp name(this is the data) {
Ex. #2: temp name() {
$1=名称,$2=数据
请注意,您的正则表达式包含一个尾随的大括号。您可以修改正则表达式使其匹配,而不使用它,这将导致:
\\s*temp\\s+([A-Za-z]+)\\s*\\(\\s*(.*)\\\\\\s*
Oh Foo.谢谢@SebastianProske-fixedIs为(and)创建数组而不是像这样简单地将它们作为单个字符转义有意义吗?
\\s*temp\\s+([a-Za-z]+)\\s*\\(\\s*(.*)\\\\\\s*.\\\\\\s*
@yoseflow这是一种风格。[(]
和\\(
在效果和字符数上是等效的。如果长度不同,我更喜欢较短的,但因为它们是相同的,我打破了可读性上的限制。我个人觉得[(]
更容易阅读。此外,一些字符在像这样“转义”时看起来很酷,例如[*]
,这总是让我想起哈,实际上我也有同样的习惯,更喜欢括号而不是转义符,但我想知道这是否会对性能造成影响。@yosefrow性能会有一点影响,因为引擎必须处理大小为1的字符列表,而不是单个字符。我只是做了一些基准测试,然后在性能危急的情况下(如自动股票交易),在订单上使用字符类转义成本为50纳秒你可能会担心,但对于正常的商业情况,没有人会在意或注意到。但其他程序员将不得不阅读并可能调试你的正则表达式,因此可读性具有真正的商业价值。必须节省这些纳秒;)