使用逻辑OR时,在Java Regex中正确使用匹配器组

时间:2017-08-17 23:48:38

标签: java regex

我必须解析一个包含纬度和数字的字符串。经度值。字符串可以采用以下两种格式之一:

Lat: 33.1234 Lon: -110.1234
Lat, Lon: 33.1234 -110.1234

我正在使用Pattern& Java中的匹配器。以下正则表达式正确匹配字符串:

Lat, Long:\s*([-\d\.]+)[\,\s]+([-\d\.]+)|Lat:\s*([-\d\.]+)\s*Lon[g]?:\s*([-\d\.]+)

然而......匹配者有4组。前两组或后两组具有lat / lon值,另外两组为null。

我意识到我可以测试null ...但我很好奇是否有一种方法只让匹配器返回两个包含lat&组的组。 lon值是否与给出的字符串格式无关?

3 个答案:

答案 0 :(得分:2)

此正则表达式匹配您的两个示例案例。

Lat(?:,\s+Long?)?:\s*([-\d\.]+)(?:\s+|\s*,\s*)(?:Long?:\s+)?([-\d\.]+)

https://regex101.com/r/D3aBpX/1

 Lat                           # Lat label
 (?: , \s+ Long? )?            # optional , Long label
 :                             # colon
 \s*                           # optional space
 ( [-\d\.]+ )                  # (1), lat value
 (?: \s+ | \s* , \s* )         # Seperated by space or comma ( must have one )
 (?: Long?: \s+ )?             # optional Long label and colon
 ( [-\d\.]+ )                  # (2), long value

答案 1 :(得分:0)

您可以测试输入是否有效,然后单独解析输入。它有点慢(两个正则表达式),但这意味着你将拥有两个可预测的捕获组。

所以你可以这样做:(显然,可以随意重复使用模式:)):

if (Pattern.compile("Lat[,:].*Long?:.*").matcher(inputString).matches()) {
    Matcher m = Pattern.compile(".*([-\d\.]+)\b.*([-\d\.]+).*")
        .matcher(inputString);
    if (m.matches()) {
        // m.group(1) is always lat, and m.group(2) is always lon
    }

}

答案 2 :(得分:0)

我能想到的一些选择(我做了同样的假设,马修对你的第二次输入做错了。)

使正则表达式更宽松并使用命名组。我认为以下内容适用于此(虽然我不能说我觉得这太可读了):

"Lat[:,](?:\\s+Long:)?\\s+(?<lat>[\\-\\+]?\\d+(?:\\.\\d+)?)(?:\\,)?(?:\\sLong?:)?\\s+(?<long>[\\-\\+]?\\d+(?:\\.\\d+)?)"

使用Scanner检查值而不是正则表达式。有点像:

final double latitude, longitude;
try (final Scanner scanner = new Scanner(input)) {

    while (!scanner.hasNextDouble()) scanner.next();
    latitude = scanner.nextDouble();

    while (!scanner.hasNextDouble()) scanner.next();
    longitude = scanner.nextDouble();
}

不幸的是,除了在其中至少有两个可解析的双精度(应该添加)之外,这并不能确认输入符合预期。然而,(至少对我来说)一目了然更具可读性。