我想写一个正则表达式来检查一个单词是否以除s,x,y,z,ch,sh或元音之外的任何内容结尾,然后是s。这是我失败的尝试:
re.match(r".*[^ s|x|y|z|ch|sh|a|e|i|o|u]s",s)
补充一组字符的正确方法是什么?
答案 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 |
。请注意,它不会尊重像ch
和sh
这样的复合组,而|
实际上会被解释为管道符,它们在字符类中多次出现(其中重复项只是被忽略了。)
所以这实际上等同于以下字符类:
[^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中有反斜杠时它才有用,这样你就不必用字符串表示法来转义它们。