2017-04-17 38 views
1

我目前正在尝试检测用户给出的文本内的任何列表。我似乎无法正确检测具有正则表达式的列表。如何使用正则表达式检测文本中的多个列表?

示例文本

a, b, c and d, or e 

规则集

\w+(,?\s*\w+)+,?\s*(and|or) 

与左侧一个字开始足以满足我的使用情况(第一\w+表示)。使用Regular Expressions 101来测试正则表达式,显示它在上面的示例文本中工作得很好。

使用Java的Matcher类,我可以简单地检查了最后一组无论是,检测连词的“类型”(这么说)。

然而,更复杂的输入将导致上市的错误检测。也就是说,多个列表被检测为一个而不是多个

多个列表实施例

a, b, c and d, or e but not f, g, h and i, or j 

再次,Regular Expressions 101只有一个列表测试被检测到(从文本的开头到达直到最后)。

那么,如何将改变正则表达式来检测多个列表,而不是所有目录作为一个?

而且,我很好与任何其他的解决方案了。我只是想尽可能地解决这个问题。


最后,有一些代码可以看到一个示例实现。

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

public class Main { 
    public static void main(String[] args) { 
     Matcher matcher = Pattern.compile("\\w+(,?\\s*\\w+)+,?\\s*(and|or)").matcher("a, b, c and d, or e but not f, g, h and i, or j"); 

     while(matcher.find()){ 
      String conjunctionType = matcher.group(matcher.groupCount()).toLowerCase(); 

      Arrays.asList(Conjunction.values()).forEach(type -> { 
       if(conjunctionType.equals(type.toString())){ 
        System.out.println("Type: " + type); 
        System.out.println("Match: " + matcher.group()); 
        // TODO: use the type for further processing 
       } 
      }); 
     } 
    } 
} 

连词枚举

public enum Conjunction { 
    AND, 
    OR; 

    @Override 
    public String toString(){ 
     return this.name().toLowerCase(); 
    } 
} 

输出

Type: or 
Match: a, b, c and d, or e but not f, g, h and i, or 

所需的输出

Type: or 
Match: a, b, c and d, or 
Type: or 
Match: f, g, h and i, or 

更新

我忘了提及,在上面的正则表达式的任何单个字母是词语的任意量仅仅是占位符。

一种更为复杂的实施例

a, b with some other words, c and d , or e but not f, g, h or i, and j 

回答

0

我终于通过使正则表达式部分非找到了解决办法贪婪。

(\b\w+\b\s*,??\s*)+, (or|and) 

注意??在正则表达式(见here了解更多信息)。最终结果见this example。虽然忽略了列表中的最后一个“项目”,但这足以满足我的用例。

示例代码

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

public class Main { 
    public static void main(String[] args) { 
     String text = "a, b, c and d, or e but not f, g, h and i, or j"; 
     String pattern = "(\\b\\w+\\b\\s*,??\\s*)+, (or|and)";  

     Matcher matcher = Pattern.compile(pattern).matcher(text); 

     while(matcher.find()){ 
      String conjunctionType = matcher.group(matcher.groupCount()).toLowerCase(); 

      Arrays.asList(Conjunction.values()).forEach(type -> { 
       if(conjunctionType.equals(type.toString())){ 
        System.out.println("Type: " + type); 
        System.out.println("Match: " + matcher.group()); 
        // TODO: use the type for further processing 
       } 
      }); 
     } 
    } 
} 

输出

Type: or 
Match: a, b, c and d, or 
Type: or 
Match: e but not f, g, h and i, or 
1

\w+未能从butnot区分a。看来,你必须做出一个逗号分隔符强制除非and使用,并明确定义and分隔符:

\w+(?:,\s*\w+(?:\s+and\s+\w+)?)+,?\s*(and|or) 

演示:https://regex101.com/r/NqlBLk/1

+0

+1使用'?',我没有想到这一点。看来,我忘了提到一些方面,对不起 - 我会更新这个问题。 – mcuenez