2013-11-13 15 views
1

Я хочу написать регулярное выражение, чтобы проверить, заканчивается ли слово чем-либо, кроме s, x, y, z, ch, sh или гласного, за которым следует s. Вот моя неудачная попытка:Regex: Дополнить группу символов (Python)

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

Каков правильный способ дополнить группу символов?

+0

Вам нужно проверить границу слова или значение '' 'именно этого слова? – LarsH

+0

Возможно, вы захотите также рассмотреть символы пробелов. Поскольку вы заявляете, что хотите проверить, заканчивается ли слово с определенной последовательностью символов, вы, вероятно, не хотите сопоставлять словосочетания, к которым применяются эти условия. Поэтому обязательно включите '\ s' в свой шаблон. – Xiphias

ответ

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, чтобы убедиться, что слово фактически заканчивается.

+1

Последний провалится словами типа 'as'. – georg

+0

Это также не сработает, если регулярное выражение совпадает с чем-то, что не является концом строки, как в 'catsup', не так ли? Поэтому вам нужно '' 'на конце. Также обратите внимание на пункт @ thg435, что переменная длина lookbehind не допускается. – LarsH

+0

@ thg435 Вы правы, спасибо! – poke

3

решение Non-регулярное выражение с помощью 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 
+2

+1 для решения, не являющегося регулярным выражением, для проблемы с необязательным регулярным выражением :) – poke

0

Как насчет

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

Использование search() вместо match() означает, что матч не должен начинаться в начале строки, поэтому мы может устранить .*.

Предполагается, что конец слова - это конец строки; то есть нам не нужно проверять границу слова.

Он также предполагает, что вам не нужно соответствовать «слову» hs, даже если оно соответствует буквально вашим правилам. Если вы хотите, чтобы соответствовать, что хорошо, вы могли бы добавить еще одну альтернативу:

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

Но опять же, мы предполагаем, что начало слова является начало строки.

Обратите внимание, что необработанная строковая нотация, r"...", здесь не требуется (но безвредна). Это помогает только тогда, когда у вас есть обратная косая черта в регулярном выражении, так что вам не нужно избегать их в строковой нотации.

+0

Это соответствует, например, «wst». Разве вы не добавляете символ конца строки или конца слова в конец регулярного выражения? –

+0

@ JoSo: Ты прав. Я тоже пришел к такому выводу. – LarsH

1

Похоже, что вам нужно отрицательное здесь: 'назад

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

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

Обратите внимание, что re не поддерживает переменной ширины LBS, поэтому вам нужно два из них.

Смежные вопросы