用简明英语列出的项目的正则表达式

时间:2014-08-01 18:31:04

标签: java regex

这是一个人为的例子,但我想在这里找到一般原则。

给出使用此类列表形式的英文短语:

I have a cat
I have a cat and a dog
I have a cat, a dog, and a guinea pig
I have a cat, a dog, a guinea pig, and a snake

我可以使用正则表达式获取所有项目,无论有多少项目?请注意,这些项目可能包含多个单词。

显然,如果我只有一个,那么我可以使用I have a (.+),如果只有两个,I have a (.+) and a (.+)可以使用。

但是,如果我想匹配的不仅仅是一个例子,事情会变得更复杂。如果我想从前两个示例中提取列表项,我认为这样可行:I have a (.*)(?: and a (.*))?虽然这适用于第一个短语,但告诉我我有一个cat和{{1} },对于第二个,它告诉我我有一个nullcat and a dog。当我尝试以更多形式匹配短语时,情况会变得更糟。

我有什么办法可以为此目的使用正则表达式吗?这似乎相当简单,我不明白为什么我的正则表达式匹配2项目列表,但匹配1或2项目列表的正则表达不起作用。

4 个答案:

答案 0 :(得分:1)

您可以将非捕获组用作条件分隔符(逗号或行尾):
' a (.*?)(?:,|$)'

python中的示例:

import re
line = 'I have a cat, a dog, a guinea pig, and a snake'
mat = re.findall(r' a (.*?)(?:,|$)', line)
print mat # ['cat', 'dog', 'guinea pig', 'snake']

答案 1 :(得分:1)

我使用正则表达式拆分来完成它。但这假设句子格式与您的输入集完全匹配:

>>> SPLIT_REGEX = r', |I have|and|, and'
>>> for sample in ('I have a cat', 'I have a cat and a dog', 'I have a cat, a dog, and a guinea pig', 'I have a cat, a dog, a guinea pig, and a snake'):
...     print [x.strip() for x in re.split(SPLIT_REGEX, sample) if x.strip()]
... 
['a cat']
['a cat', 'a dog']
['a cat', 'a dog', 'a guinea pig']
['a cat', 'a dog', 'a guinea pig', 'a snake']

答案 2 :(得分:1)

您可以使用\G方法使用find锚点:

(?:\G(?!\A)(?:,? and|,)|\bI have) an? ((?>[b-z]+|\Ba|a(?!nd\b))+(?> (?>[b-z]+|\Ba|a(?!nd\b))+)*)

或更简单:

(?:\G(?!\A)(?:,? and|,)|\bI have) an? ((?!and\b)[a-z]+(?> (?!and\b)[a-z]+)*)

\G是最后一次匹配后字符串中的位置。该模式有两个入口点。第一个匹配将使用第二个入口点:\bI have,然后匹配,第一个入口点只允许连续的结果。

注意:\G表示匹配最后一次匹配后的位置,但它也匹配字符串的开头。 (?!\A)是为了避免这种情况。

online demo

regex planet (点击Java按钮)

答案 3 :(得分:0)

使用正向前瞻性regexp提供一个java实现。见下文:

String str0 = "I have a cat";
String str1 = "I have a cat and a dog";
String str2 = "I have a cat, a dog, and a guinea pig";
String str3 = "I have a cat, a dog, a guinea pig, and a snake";

String regexp = "(?m)\\ba\\s+.*?(?=(?:,|$|and))";

Pattern pMod = Pattern.compile(regexp);
Matcher mMod = pMod.matcher(str3);

while (mMod.find()) {
    System.out.println(mMod.group(0));
}

对于str3,输出为:

a cat
a dog
a guinea pig
a snake

如果该项目可以是'a','an'或'one',那么正则表达式可以是(?m)\\b(one|an|a)\\s+.*?(?=(?:,|$|and))

(?m)表示在进行解析时启用MULTILINE标志。 在多行模式中,表达式^和$分别在行终止符之后或之前或输入序列的末尾匹配。默认情况下,这些表达式仅匹配整个输入序列的开头和结尾。