正则表达式使用lookahead和lookbehind从匹配的内容中仅提取String

时间:2014-11-17 10:25:39

标签: java regex regex-lookarounds

考虑以下文本,该文本是文件的一部分

  

姓名& Emp No
Jack Doe 1234
John 12345
  28/12/1987

现在我想编写一个正则表达式( java flavor )来仅提取上述文本中的名称。

我使用lookahead和lookbehind

尝试了以下正则表达式
(?<=(Name\s&\sEmp\sNo)\s{2,3})((.{1,100}\s{0,3}){0,5}?)(?=Dob)

,我得到的输出是

Jack Doe 1234[CR][LF]John 12345[CR][LF]

如果我只想将名称作为输出,我该如何修改这个正则表达式?

3 个答案:

答案 0 :(得分:0)

以下是基于以下假设的尝试:名称出现在行的开头,后跟数字:

String test = 
    "Name & Emp No\r\n" +
    "Jack Doe 1234\r\n" + 
    "John 12345\r\n" +
    "Dob : 28/12/1987";
//                           | start of line
//                           | | alphabetics and whitespace
//                           | |             | greedy quantifier
//                           | |             | | lookahead for digits
//                           | |             | |        | multi line pattern
Pattern p = Pattern.compile("^[\\p{Alpha}\\s]+(?=\\d)", Pattern.MULTILINE);
Matcher m = p.matcher(test);
while (m.find()) {
    System.out.println(m.group());
}

<强>输出

Jack Doe 
John 

注意

  • 这里的诀窍是"Name ""Dob "都不匹配 因为它们后面没有数字。
  • 匹配的名称最后只有一个空格(您可以使用String.trim()进行清理)

答案 1 :(得分:0)

这个正则表达式可以帮助你。

^([[:alpha:]]+[ ]?)+(?=[ ]+\d+)

Regex Demo

答案 2 :(得分:0)

这是一个单线解决方案:

String[] names = str.replaceAll("(?s).*No\\s+|\\s+Dob.*", "").split("\\s+\\d+\\s*");

这会剥离前导和尾随垃圾,然后拆分空格 - 然后 - 数字 - 然后 - 可选 - 空格。

这里有一些关键点:

  • 使用DOTALL标志(?s),这使得点匹配换行符
  • 空白\s匹配换行符
  • java&#39; s split()默认丢弃尾随空白元素(这就是为什么不需要处理姓氏后面的尾随数字。
  • 这适用于任何数量的&#34;名称然后数字&#34;页眉和页脚之间的行

一些测试代码:

String str = "Lots of lines\r\nName & Emp No\r\nJack Doe 1234\r\nJohn 12345\r\nDob : 28/12/1987\r\nLots more lines";
String[] names = str.replaceAll("(?s).*No\\s+|\\s+Dob.*", "").split("\\s+\\d+\\s*");
System.out.println(Arrays.toString(names));

输出:

[Jack Doe, John]