正则表达式 - Lookbehind没有固定长度

时间:2017-02-28 13:49:17

标签: java regex string nlp pattern-matching

我正在尝试使用Java RegEx匹配句子中的名称。仅当名称被普通文本而不是其他名称包围时,才应匹配名称。例如,我想在下面的句子中匹配 Obama 这个词:

Americans said that Obama is ...

但不是以下一个:

Americans said that Barack Obama is ...

要检查令牌是否是名称,我需要使用简单的(简单的正则表达式),而不依赖于更复杂的工具(即NER)。正则表达式使用非固定宽度量词(*):

[A-Z][a-z]*

我可以很容易地找到一种避免匹配名称的方法,其次是其他名称与否定前瞻,因为我不能在负面的后视中使用相同的正则表达式,因为存在未固定的宽度量词

换句话说,我不能使用以下正则表达式:

(?<![A-Z][a-z]*\s)Obama(?!\s[A-Z][a-z]*)

你有什么其他简单但有效的想法来解决这个问题吗?

1 个答案:

答案 0 :(得分:1)

Java正则表达式引擎确实不支持无限宽度的后视模式,但是,Java lookbehind模式是约束宽度,这意味着,我们可以使用{{1在其中限制量词(设置最小值和最大值)。

所以,你可以使用

{n,m}

请参阅Java online demo

由于这假设前面的单词可以是1到101个字母长,这不是最好的方法,但可能会变得足够。

此外,您可以依赖捕获:

String str = "Americans said that Obama is ... Americans said that Barack Obama is ...";
Pattern ptrn = Pattern.compile("(?<!\\b[A-Z][a-z]{0,100}\\s)Obama(?!\\s+[A-Z][a-z]*)");
Matcher matcher = ptrn.matcher(str);
while (matcher.find()) {
    System.out.println(matcher.group(0));
}

请参阅another demoPattern ptrn = Pattern.compile("(^|\\s[a-z]+\\s+)(Obama)(?!\\s+[A-Z][a-z]*)"); // ... while (matcher.find()) { System.out.println(matcher.group(2)); } 将出现在第2组,第1组将匹配并使用Obama - 字符串的开头,或者空格+一个或多个小写ASCII字母和1 +空格。