Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 用普通英语列出的项目的正则表达式_Java_Regex - Fatal编程技术网

Java 用普通英语列出的项目的正则表达式

Java 用普通英语列出的项目的正则表达式,java,regex,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 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
我是否可以使用正则表达式获取所有项,而不管有多少项?请注意,这些项目可能包含多个单词

显然,如果我只有一个,那么我可以使用
我有一个(+++
,如果正好有两个,
我有一个(+++)和一个(+++

但如果我想匹配不止一个例子,事情就会变得更复杂。如果我想从前两个示例中提取列表项,我认为这会起作用:
我有一个(.*)(?:和一个(.*)?
,当这对第一个短语起作用时,告诉我有一个
cat
null
,第二个短语告诉我有一个
猫和一只狗
null
。当我尝试以更多的形式匹配短语时,事情只会变得更糟


我有没有办法使用正则表达式来达到这个目的?这似乎相当简单,我不明白为什么匹配2项列表的正则表达式有效,但匹配1项或2项列表的正则表达式无效。

您可以使用非捕获组作为条件分隔符(逗号或行尾):
“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']

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

>>> 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']

您可以使用
\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)
是为了避免这种情况


(单击Java按钮)

使用正向前瞻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+.*(?=(?:,|$|和))

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

如果格式一致,可能会匹配,但英语作为一个整体不是一种常规语言。您使用什么编程语言来测试表达式?是的,它总是完全按照我描述的格式,带有(第一项)(中间项,用逗号和冠词分隔)(最后项用逗号和单词“and”和冠词),中间项和最后项是可选的。另外,这是在Java中。用冒号分割不是更好吗?不错,但至少在Java中,这不适用于第二个示例(
我有一只猫和一只狗
)。这似乎是可行的:
“a(.*?(:,|和|$)”
但是在循环中查找它们肯定比我一次查找所有的方法要好。这很有效,但它给了我一些零长度匹配(不过我使用的是Java)。它还保留了
a
s,但是使用split可能比我的方法更好。我想我是在尝试匹配这种形式的短语,同时提取项目,但最好是独立完成每一项。@codebreaker我会在后续步骤中剥离文章。特别是因为有“a”和“an”的区别。不想让正则表达式太复杂。@codebreaker零长度匹配被
if x.strip()
子句过滤掉。哦,好的。我没有看到
if x.strip
子句。这是有道理的。这是一个很好的正则表达式,它运行得很好,但是它比@alfasin做的事情有什么优势吗?这似乎简单多了。@codebreaker:是的,因为此模式只允许连续匹配,所以它确保字符串格式符合您的要求。例如,在较大的字符串中,此模式无法与“白兔”匹配。这个句子必须以“我有”开头。这种模式捕获您想要的元素,同时检查格式。@codebreaker:注意,您可以通过使用小技巧测试最后一个匹配是否在字符串末尾来改进它。修饰符
(?m)
的作用是什么?我在回答中添加了解释。谢谢。我知道这个修饰词是用来做什么的。但为什么要将其添加到表达式中?所有的例子都是单行的。嗨,是的。在我的代码中,输入是单行的,(因此,(?m)不是必需的),如果用户从文件中获得整个输入,它将非常有用。谢谢。