我有一个匹配以下行之一的正则表达式:
[.,!?;]
以下是有问题的正则表达式([.,!?;] *|(?<= |\A)[\-'’:\w]+)
我需要它做的是它匹配3个这样的实例。因此,例如,理想的最终结果将是这样的。
Sample text: "This is a test. Test"
Output
"This" "is" "a"
"is" "a" "test"
"a" "test" "."
"test" "." "Test"
我试过简单地将{3}
添加到最后,希望它匹配3次。然而,这导致它根本不匹配或偶尔匹配奇怪的字符。我尝试过的另一种可能性就是重复整个正则表达式3次,如([.,!?;] *|(?<= |\A)[\-'’:\w]+)([.,!?;] *|(?<= |\A)[\-'’:\w]+)([.,!?;] *|(?<= |\A)[\-'’:\w]+)
这样看起来很可怕,但我希望它能起作用。这有一个奇怪的工作效果,但前提是至少有一个匹配是之前列出的标点之一。
任何见解都将不胜感激。
我正在使用new regex module found here,以便我可以重叠搜索。
答案 0 :(得分:1)
您的方法出了什么问题
([.,!?;] *|(?<= |\A)[\-'’:\w]+)
模式匹配单个“单位”(来自指定集合[.,!?;]
的单词或单个标点符号,后跟0 +空格。因此,当您将此模式提供给{{ 1}},它只能返回块列表regex.findall
。
<强>解决方案强>
您可以使用稍微不同的方法:匹配所有单词,以及所有不是单词的块。这是一个演示(请注意,['This', 'is', 'a', 'test', '. ', 'Test']
和C'est
被视为单个“字词”):
AUX-USB
此处,模式有3个捕获组,第二个和第三个模式包含与组1中相同的模式(>>> pat = r"((?:[^\w\s'-]+(?=\s|\b)|\b(?<!')\w+(?:['-]\w+)*))\s*((?1))\s*((?1))"
>>> results = regex.findall(pat, text, overlapped = True)
>>> results
[("C'est", 'un', 'test'), ('un', 'test', '....'), ('test', '....', 'aux-usb')]
是一个子程序调用,用于避免重复第1组中使用的相同模式。第2组和第3组可以用空格分隔(不一定,或者粘在一个单词上的标点符号不匹配)。另外,请注意负面的后视(?1)
,以确保将(?<!')
视为单个实体。
<强>解释强>
模式细节:
C'est
- 第1组匹配:
((?:[^\w\s'-]+(?=\s|\b)|\b(?<!')\w+(?:['-]\w+)*))
- (?:[^\w\s'-]+(?=\s|\b)
以外的1个以上字符,空格,[a-zA-Z0-9_]
和'
后面紧跟空格或字边界-
- 或|
- 1个单词字符前面没有\b(?<!')\w+(?:['-]\w+)*)
(由于'
),前面有一个单词边界((?<!')
),后面跟着0+序列\b
或-
后跟1个字符。'
- 0+ whitespaces \s*
- 第2组(与第1组相同的模式)((?1))
- 见上文