我目前正在尝试检测用户提供的文本中的所有商家信息。我似乎无法通过正则表达式正确检测这些列表。
示例文字
a, b, c and d, or e
规则集
\w+(,?\s*\w+)+,?\s*(and|or)
从左侧的一个单词开始就足以满足我的用例(由第一个\w+
表示)。使用Regular Expressions 101测试正则表达式,表明它可以正常使用上面的示例文本。
使用Java的Matcher
课程,我只需检查最后一组是否是和或或,检测"类型"结合(可以这么说)。
但是,更复杂的输入会导致错误检测列表。也就是说,多个列表被检测为 one 而非多个。
多个列表示例
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 :(得分:1)
\w+
无法区分a
与but
或not
。除非使用and
,否则您必须将逗号设为强制分隔符,并明确定义and
分隔符:
\w+(?:,\s*\w+(?:\s+and\s+\w+)?)+,?\s*(and|or)
答案 1 :(得分: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