正则表达式:补充一组字符(Python)

时间:2013-11-13 09:44:40

标签: python regex string

我想写一个正则表达式来检查一个单词是否以除s,x,y,z,ch,sh或元音之外的任何内容结尾,然后是s。这是我失败的尝试:

re.match(r".*[^ s|x|y|z|ch|sh|a|e|i|o|u]s",s)

补充一组字符的正确方法是什么?

4 个答案:

答案 0 :(得分:3)

使用str.endswith的非正则表达式解决方案:

>>> from itertools import product
>>> tup = tuple(''.join(x) for x in product(('s','x','y','z','ch','sh'), 's'))
>>> 'foochf'.endswith(tup)
False
>>> 'foochs'.endswith(tup)
True

答案 1 :(得分:2)

[^ s|x|y|z|ch|sh|a|e|i|o|u]

这是倒置字符类。字符类匹配单个字符,因此在您的情况下,它将匹配任何字符,但其中一个字符除外:acehiosuxyz |。请注意,它会尊重像chsh这样的复合组,而|实际上会被解释为管道符,它们在字符类中多次出现(其中重复项只是被忽略了。)

所以这实际上等同于以下字符类:

[^acehiosuxyz |]

相反,您必须使用负面外观,以确保尾随s 前面有任何字符序列:

.*(?<!.[ sxyzaeiou]|ch|sh)s

这个问题是它无法匹配两个字符,因为,为了能够使用外观,后面的外观需要有一个固定的大小。并且要在后面的外观中包含单个字符和双字符组,我必须在单个字符匹配中添加另一个字符。但是,您可以使用两个单独的外观:

.*(?<![ sxyzaeiou])(?<!ch|sh)s

正如LarsH在评论中提到的,如果你真的想匹配以此结尾的单词,你应该在表达式的末尾添加某种边界。如果你想匹配字符串/行的结尾,你应该添加$,否则你应该至少添加一个单词边界\b以确保实际这个词结束< / em>那里。

答案 2 :(得分:1)

看起来你需要一个负面的背后隐藏:

import re
rx = r'(?<![sxyzaeiou])(?<!ch|sh)s$'

print re.search(rx, 'bots')  # ok
print re.search(rx, 'boxs')  # None

请注意,re不支持可变宽度的LB,因此您需要其中两个。

答案 3 :(得分:0)

怎么样

re.search("([^sxyzaeiouh]|[^cs]h)s$", s)

使用search()代替match()表示匹配不必从字符串的开头开始,因此我们可以删除.*

这假设单词的结尾是字符串的结尾;即我们不必检查单词边界。

它还假设您不需要匹配“单词”hs,即使它符合您的规则。如果你想匹配它,你可以添加另一种选择:

re.search("([^sxyzaeiouh]|[^cs]|^h)s$", s)

但同样,我们假设单词的开头是字符串的开头。

请注意,原始字符串表示法r"..."在此处是不必要的(但无害)。只有在regexp中有反斜杠时它才有用,这样你就不必用字符串表示法来转义它们。