我正在尝试将一段C#代码翻译成Java,虽然我对这两种代码都很熟悉,但我对正则表达式库不是很熟悉。
在MSDN中,他们给出了这个例子
String pattern = @"D+(?<digit>d+)D+(?<digit>d+)?";
这个输出(我看到他们使用的是捕获索引,而不是组名本身)
Match: abc123def456
Group 1: 456
Capture 0: 123
Capture 1: 456
有了这个纸币
组名可以在正则表达式中重复。例如,可以将多个组命名为数字,如下例所示。在名称重复的情况下,Group对象的值由输入字符串中最后一次成功捕获的值确定。
所以这可能是一个糟糕的例子(因为我的实际代码没有使用数字),但无论如何。。。
将其转换为Java,它对第二个<digit>
并不太满意。
String pattern = "\D+(?<digit>\d+)\D+(?<digit>\d+)?"
Pattern p = Pattern.compile(pattern);
String matchMe = "abc123def456";
和在Pattern.compile
的错误
Named capturing group <digit> is already defined
我想,完全删除除了姓氏之外的所有名字将是一种选择,因为这将"匹配"C#行为。
然而,当我试图像一样将模式嵌套在另一个模式中时,就会出现这个问题
String x = "(?<InnerData>...)no group(?<InnerGroup>foo)";
String y = "(?<header>[...])some data" + x + "more regex" + x;
Pattern.compile(y);
其中x
是在y
中重复的内部内容,并且它不是我可以粘贴重复修饰符的东西。
我知道拥有相同名称的组是没有意义的,因为它怎么知道你想要什么?
所以,问题是——我该怎么办
使用Matcher.group(int)
是我唯一的选择并放弃组名吗?
如果我至少正确理解了这个问题,那么使用regex就无法做到这一点。如果您能提供一些示例数据,那么这些数据将非常有用。
第一个
"(?<header>[...])some data" + x1 + "more regex" + x2
对于您的示例,只要x1
和x2
是具有不同组名的同一正则表达式,这就可以工作。但我相信这不是你想要的。
第二次
假设字符串:FEW014 BKN025CB
我有三个我感兴趣的参数,比如说:
a可以是OVC
、FEW
或BKN
h可以是任意一组恰好为3位的
t可以是CB
、TCU
或不存在
此外,这些参数的字符串可以具有这3个参数的多达4次出现;这个例子有2个,但是可以增加到4个。
现在假设regex(匹配这3个参数):
(?P<a>FEW|BKN|OVC)(?P<h>[d]{3})(?P<t>CB|TCU)?
我可以使用正则表达式引擎来获得这些参数的所有出现的列表,但引擎不会将它们相互关联。
我会得到如下的东西:
a:
FEW
BKN
h:
014
025
t:
CB
看看我是怎么忘记CB
的来源的?这是预期的行为,因为正则表达式引擎不会保持状态。他们只是把东西塞进桶里。
最后
实现这一点的方法是,不要贪婪地使用正则表达式,只需匹配一次相关的东西,存储它们,然后继续。
--
我在那里使用的第二个例子是从一个真实世界的案例中偷来的,在这个案例中实现了这一点;只是为了简单起见更改了一些名称。
FEW014 BKN025CB
是文本气象报告的一部分,以解释的方式进行解析。
希望它能帮助你理解这笔交易,以下是实现这一点的代码:
@occurs(4)
@search(r"""
(?P<amount>FEW|SCT|BKN|OVC)
(?P<height>[d]{3}|///)
(?P<type>CB|TCU|///)?
""")
def pclouds(item):
"""Returns ((amount, height, type),) of ((string, int, string),) for
clouds or ()"""
tcloud = namedtuple('Cloud', 'amount height type')
height = item['height']
if height == '///':
height = -1
else:
height = int(height)
return tcloud(item['amount'], height, item['type'])
https://github.com/pedro2555/avweather/blob/master/avweather/_metar_parsers.py#L221
- 搜索装饰器,搜索给定正则表达式的一个实例
- 出现装饰器,重复搜索给定次数
- 调用
pclouds
函数,注意item
只保存一组3个值
为什么需要命名组?
我认为这对你的问题没有必要。它只找到与find
的连续匹配在这种情况下,唯一的组是组1。
导入java.util.regex.Matcher;导入java.util.regex.Pattern;
public class Main
{
public static void main(String[] args) {
String patt = "\D+(\d+)";
String target = "abc123def456";
Pattern pattern = Pattern.compile(patt);
Matcher matcher = pattern.matcher(target);
while (matcher.find()) {
System.out.println(matcher.group(1));
}
}
}
程序退出:
123
456
演示