【问题标题】:Regular expression with conditional extraction带条件提取的正则表达式
【发布时间】:2015-09-11 22:56:35
【问题描述】:

我有类似的句子

1 1994 FORD 5640 2WD Tractor

2 AG-GATOR 1004 4x4 Tree Spade Truck

3 2004 ROSCO RB48 Broom

4 TENNANT 830II Street Sweeper

我需要使用正则表达式从中提取单词

5640
1004
RB48
830II

即在一个句子中,如果在第一个句子中有诸如 1994 年的年份,我需要得到第 4 个单词(5640)如果没有像第 2 个句子这样的年份,我需要得到第 3 个单词(1004)

谁能建议我一个正则表达式来实现这个???..

【问题讨论】:

标签: java regex


【解决方案1】:

使用正则表达式

\d+\s(?:\d{4}\s\S*?\s(\S+)|\S+\s(\S+))

Test regex here

  1. \d+ 为索引号
  2. \d{4}\s\S*?\s(\S+) 第一种
  3. \S+\s(\S+) 匹配

更新:对于使用字母数字的索引

(?<=^|\n)\w+\s(?:\d{4}\s\S*?\s(\S+)|\S+\s(\S+))

Test regex here

使用(?&lt;=^|\n),正向查找字符串应该在开头或换行符之后

【讨论】:

  • 不知道那个 regex101 网站,谢谢分享。
  • 但上面的正则表达式不起作用“4A 1998 BROCE RJ350 Broom”句子
  • @vineethPrabhakaran 您没有指定第一个字段可以是字母数字。然后将\d+替换为\S+,所以\b\S+\s(?:\d{4}\s\S*?\s(\S+)|\S+\s(\S+))\b
【解决方案2】:

假设布局有些恒定(从您的问题看来),只需将年份设为可选:

^\d+ (?:\d{4} )?\S+ (\S+)

表达式分解:

  • ^输入开始
  • \d+ 后跟空格字符的数字序列
  • (?:\d{4} )? 可选 4 位数字序列,后跟空格字符
  • \S+ 一系列非空白字符,后跟一个空格字符
  • (\S+) 一系列非空白字符作为捕获组 - 这就是您所追求的

如果您想支持中间的任何空格以及可能的任何长度,请使用 \s+ 而不仅仅是空格字符。

使用 PatternMatcher 类在每个句子上应用正则表达式,并在匹配器上使用 group(1) 来提取您要查找的组的内容。

编辑:注意\d 将匹配任何类型的数字。如果您只想允许 ascii 数字 0-9,请改用 [0-9]

根据您想限制可能的年份数字的程度,您可能还想扩展该表达式,例如(19|20)[0-9]{2} 而不是 \d{4}

【讨论】:

    【解决方案3】:

    /\d{4}(?!.*\d{4})/g 呢?使用否定前瞻跳过不匹配的字符。

    编辑:此正则表达式匹配文本中的最后 4 位数字序列。

    【讨论】:

    • 我只是展示了如何使用负前瞻。我不会破坏自己创建正则表达式的乐趣:)
    【解决方案4】:

    你可以试试:

    (?=^(?:.*\d{4}\s)?[-a-zA-Z]+\s([a-zA-Z0-9]+))
    

    DEMO

    这意味着:

    • (?= - 积极的前瞻:
    • ^ - 行首,
    • (?:.*\d{4}\s)? - 四位数字和空格,
    • [-a-zA-Z]+\s - 一个或多个字母和一个规格,
    • ([a-zA-Z0-9]+) - 一个或多个字母或数字(期望值)

    此正则表达式通过前瞻分组进行匹配,因此它不会匹配任何文本,只是文本中的零长度点,但您可以通过group(1) 获取值。 Java 中的示例:

    public class Test{
        public static void main(String[] args){
            String[] array = {"1994 FORD 5640 2WD Tractor","AG-GATOR 1004 4x4 Tree Spade Truck","2004 ROSCO RB48 Broom",
                    "TENNANT 830II Street Sweeper","4A 1998 BROCE RJ350 Broom"};
            Matcher matcher = null;
            for(String element : array) {
                matcher = Pattern.compile("(?=^(?:.*\\d{4}\\s)?[-a-zA-Z]+\\s([a-zA-Z0-9]+))").matcher(element);
                if (matcher.find()) {
                    System.out.println(matcher.group(1));
                }
            }
        }
    }
    

    另一种方式,但仅适用于 Java,是直接匹配:

    (?<=^(?:.{0,99}\d{4}\s)?[-a-zA-Z]{1,99}\s)[a-zA-Z0-9]+
    

    DEMO

    这是在没有固定长度的情况下使用正向后视。它使用了相当丑陋的结构,语法如:.{0,99}(从零到 99 个字符)等。在大多数正则表达式风格中,您不能在后视中使用 quantifires,但 Java 允许使用 ? 和具有最小值和最大值的间隔(@ 987654334@)。它不太优雅,但在这种情况下有效。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-01-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多