如何优化正则表达式模式?

How to optimize a regex pattern?

我正在尝试从文本中获取子字符串并使用正则表达式。 示例文本:

bla bla 1:30-2pm bla bla 5-6:30am some text 1-2:15am

我正在寻找时间范围条目(1-30-2pm...)。将它们加粗只是为了便于阅读

这是我的正则表达式:

\d{1,2}(:\d{1,2})? – \d{1,2}(:\d{1,2})?(am|pm)

java 片段:

public static List<String> foo(String text, String regex) {
    List<String> entries = new ArrayList<>();
    Matcher matcher = Pattern.compile(regex).matcher(text);
    while (matcher.find()) {
        entries.add(matcher.group());
    }
    return entries;
}

你能帮我优化正则表达式模式吗?可能有一些我错过的用例。

我建议使用像

这样的正则表达式
String regex = "(?i)(?<!\d)(?:0?[1-9]|1[0-2])(?::[0-5]\d)?\p{Pd}(?:0?[1-9]|1[0-2])(?::[0-5]\d)?[ap]m\b";

regex demo

详情

  • (?i) - 不区分大小写的标志(对于 AMPMampm 值等)
  • (?<!\d) - 不允许紧靠左边的数字
  • (?:0?[1-9]|1[0-2]) - 一个可选的 0,然后是从 19 的数字,或者 1 然后是 012
  • (?::[0-5]\d)? - 可选组:从 05 的数字,然后是任何一个数字
  • \p{Pd} - 任何连字符
  • (?:0?[1-9]|1[0-2])(?::[0-5]\d)? - 见上文
  • [ap]m\b - ap 然后是 m 和单词边界。

如果我们想优化我们的表达式,我们可能想要添加可选空格,以防我们的输入可能有任何额外的空格,除此之外,您的表达式看起来很棒:

(\d{1,2})(:\d{1,2})?(\s+)?-(\s+)?(\d{1,2})(:\d{1,2})?(am|pm)

如果我们想获取数据,我们还添加了捕获组。

Demo 1

或者:

(\d{1,2})(:\d{1,2})?(\s+)?(am|pm)?(\s+)?-(\s+)?(\d{1,2})(:\d{1,2})?(\s+)?(am|pm)

Demo 2

无论你想要哪个。

测试

import java.util.regex.Matcher;
import java.util.regex.Pattern;

final String regex = "(\d{1,2})(:\d{1,2})?(\s+)?-(\s+)?(\d{1,2})(:\d{1,2})?(am|pm)";
final String string = "bla bla 1:30-2pm bla bla 5-6:30am some text 1-2:15am\n"
     + "bla bla 1:30 - 2pm bla bla 5  - 6:30am some text 1 - 2:15am";

final Pattern pattern = Pattern.compile(regex, Pattern.MULTILINE | Pattern.CASE_INSENSITIVE);
final Matcher matcher = pattern.matcher(string);

while (matcher.find()) {
    System.out.println("Full match: " + matcher.group(0));
    for (int i = 1; i <= matcher.groupCount(); i++) {
        System.out.println("Group " + i + ": " + matcher.group(i));
    }
}

正则表达式

如果不需要此表达式并且您希望对其进行修改,请访问此 link regex101.com

正则表达式电路

jex.im 可视化正则表达式: