查找单个正则表达式以在两个特定单词之间获得3个或更多字符的单词

时间:2015-09-05 17:33:21

标签: java regex

我正在寻找一个正则表达式(在Java中使用),以便在以下所有句子中获得以下单词(Peach,Apple)之间的所有3个或更多单词:

Peach are nice fruits. Apple are not.

此时,我正在使用以下部分:

\w{3,}\b

获取所有3个以上字符的单词。我正在使用正面和负面的外观来获取PeachApple之间的单词:

(?<=Peach).*(?=Apple).

我不能使用两个正则表达式,我不能使用子字符串或任何其他技术。只有一个正则表达式来提取单词。

2 个答案:

答案 0 :(得分:3)

您可以在lookbehind中使用\G

Pattern p = Pattern.compile("(?<=(?:\\bPeach\\b|\\G)\\W).*?\\b((?!Apple\\b)\\w{3,})\\b");

String msg = "Peach a nice family of fruits. Apple are not.";
Matcher m = p.matcher( msg );

while (m.find()) {
    System.out.println( m.group(1) );
}
  • \G在上一场比赛结束时或第一场比赛的字符串开头处断言位置。
  • (?<=(?:\\bPeach\\b|\\G)\|W)会在lookbehind中声明文字"Peach "\G
  • (?!Apple\\b)将确保完整字Apple不在当前位置之前
  • \\b\\w{3,}\\b将匹配0个或更多任意字符后的3个或更多字符的完整单词。

<强>输出:

nice
family
fruits

如果字符串中有多个Peach和Apple ,那么您可以使用:

String msg = "Peach, a nice family of fruits. Apple are not. Another Peach foo bar is here Apple end.";
Pattern p = Pattern.compile(
      "(?:(?<=\\bPeach\\b|\\G)\\W)(?:(?!\\bApple\\b).)*?\\b((?!Apple\\b)\\w{3,})\\b");

Matcher m = p.matcher(msg);
while (m.find()) {
    System.out.println(m.group(1));
}

<强>输出

nice
family
fruits
foo
bar
here

RegEx Demo

这个看起来很笨拙的正则表达式可能会处理许多边缘情况,但只有在嵌套/不平衡Peach/Apple对的要求时才应该使用它:

(?:(?<=\bPeach\b(?!(?:(?!\bApple\b).)*?\bPeach\b)|\G)\W)(?:(?!\bApple\b).)*?\b((?!Apple\b)\w{3,})\b

RegEx Demo 2

答案 1 :(得分:0)

您可以分两步完成,而不是编写完成所有工作的单个正则表达式:

  1. 匹配标记之间的子串。
  2. 对于每个子字符串,提取的作品超过3个字符。
  3. 这种方法可以简化正则表达式,并且在边缘情况下不易出错。

    以下面的字符串为例:

      桃子,一个很好的水果家庭苹果不是。另一个Peach foo酒吧就在这里Apple。 Peach里面的Apple Peach然后Apple Peach没有没有Apple

    我使用正则表达式(?<=\bPeach\b).*?(?=\bApple\b)来挑选子字符串 , a nice family of fruits  foo bar is here  inside Peach then  no no ,然后从这些子字符串中提取包含3个或更多字符的字词。

    上面的正则表达式只是一个例子。根据您在边缘情况下的要求,您可以自定义正则表达式以仅提取要从中提取单词的子字符串。

    您可以将上面的正则表达式更改为(?<=\bPeach\b).*(?=\bApple\b),以获取第一个Peach和最后一个Apple之间的所有内容。

    上述示例的输出为:

    [nice, family, fruits, foo, bar, here, inside, Peach, then]
    

    根据您的需要,您可以按照上面的建议更改正则表达式,或者只是简单地过滤输出。

    完整的示例代码:

    import java.util.ArrayList;
    import java.util.List;
    import java.util.regex.Matcher;
    import java.util.regex.Pattern;
    import java.util.regex.PatternSyntaxException;
    
    
    class SO32415895 {
        public static void main(String[] args) {
            String input = "Peach, a nice family of fruits Apple are not. Another Peach foo bar is here Apple. Apple Peach inside Peach then Apple Peach no no Apple";
    
            List<String> inBetween = findAll("(?<=\\bPeach\\b).*?(?=\\bApple\\b)", input);
    
            List<String> words = new ArrayList<>();
            Pattern WORD_PATTERN = Pattern.compile("\\b\\w{3,}\\b");
    
            for (String s: inBetween) {
                words.addAll(findAll(WORD_PATTERN, s));
            }
    
            System.out.println(words);
        }
    
        public static List<String> findAll(String pattern, String input) throws PatternSyntaxException {
            return findAll(Pattern.compile(pattern), input);
        }
    
        public static List<String> findAll(Pattern pattern, String input) {
            Matcher m = pattern.matcher(input);
            List<String> out = new ArrayList<>();
    
            while (m.find()) {
                out.add(m.group());
            }
    
            return out;
        }
    }