假设我有这样的字符串:
"DT NN IN NN"
"DT RB JJ NN"
"DT JJ JJ NN"
"DT RB RB NN NN"
"DT RB RB"
所以,我有一个字符串列表:
list = ["DT NN IN NN", "DT RB JJ NN", "DT JJ JJ NN", "DT RB RB NN NN", "DT RB RB"]
我有以下代码:
pattern = "(?:DT\s+)+([?:RB\s+|?:JJ\s+])+(?:NN\s+)*NN$"
for item in list:
m = re.match(pattern, item)
if m:
print item
我想从pattern
得到的是匹配以DT
开头的字符串(出现一次或多次)RB
或JJ
(出现一次或多次) ),但不是两者,然后以NN
结束(再次出现一次或多次)。
因此,在最终结果中,我应该在屏幕上打印3和4。但是,我的正则表达式,另外我得到2,我不想要。如何更改pattern
以便这可行?如何用XOR更换管道(OR)?
答案 0 :(得分:2)
问题在于如何定义RB
和JJ
的存在。你没有提到只有它们中的任何一个应该存在。这可以通过用|
(管道)分离它们并让它们中的任何一个重复一次或多次(+
)来实现。尝试将模式更改为:
pattern = "(?:DT\s+)+(?:(RB\s+)+|(JJ\s+)+)(?:NN\s+)*NN$"
此外,(?:<something>)
被称为非捕获组。你用它来说“我希望<something>
匹配,但是当我稍后选择组时不包括它。而从它的外观来看,你没有使用任何组。你只是打印整个{{1} (除非你为了简洁而屏蔽了代码)。如果你实际上不需要组,这里有一个适合你的简单版本:
item
我还让白色空格的结束集合出现0次或更多次,而不是像原始模式那样出现一次或多次。随意改变它。
答案 1 :(得分:1)
[...]
是字符类,您要匹配包含?
,:
和+
以及{{1}的一组字符等等。除了|
标记系列之外,字符类中没有修饰符或特殊字符。
您需要匹配重复-
或RB
:
JJ
我把它简化了;你还没有使用任何一组。
此模式的在线演示:https://regex101.com/r/iH4lE6/1
由于您不依赖捕获组,因此使用非捕获组也没有任何意义;只需使用pattern = r"(?:DT\s+)+(?:(?:RB\s+)+|(?:JJ\s+)+)NN"
代替(...)
即可获得更简洁的正则表达式。
您可能希望添加锚点以确保(?:...)
仅在开始时匹配,并将最后的DT
替换为NN
以将其锚定在最后,并移动与每个重复组的开头匹配的空格:
(NN\s+)*NN$
此版本的在线演示:https://regex101.com/r/iH4lE6/2
答案 2 :(得分:1)
如果我正确理解了这个问题,你可以先把它分成两个不同的问题来解决这个问题:
以RB
开头,后跟一个或多个NN
s后跟一个或多个^DT(\s+DT)*(\s+RB)+(\s+NN)+$
的正则表达式:
DT
以JJ
开头,后跟一个或多个NN
s后跟一个或多个^DT(\s+DT)*(\s+JJ)+(\s+NN)+$
的正则表达式:
^((DT(\s+DT)*(\s+RB)+(\s+NN)+)|(DT(\s+DT)*(\s+JJ)+(\s+NN)+))$
现在你可以简单地在这两者之间放一个管道(或操作员):
^DT(\s+DT)*((\s+RB)+|(\s+JJ)+)(\s+NN)+$
以后通过将其重构为:
来简化它VectorDrawables
或使用Regexper的可视化表示: