2017-01-29 4 views
0

Я хотел бы написать регулярное выражение, которое разбивает слово на cvc (согласные/гласные/согласные) или vcv-группы. Что-то похожее на ngrams, но с использованием воев и согласных. Вот пример:Как извлечь группы согласных/гласных из слова?

helloworld 

будет производить следующие группы:

hell 
ello 
llow 
owo 
world 

Я написал следующее регулярное выражение:

(?=(([aeiouy]+|[^aeiouy]+){3})) 

Первая часть ([aeiouy]+|[^aeiouy]+){3} захвата либо VCV или CVC группа , остальное (?=()) - положительное утверждение. Она не работает, как ожидалось:

hell 
ello 
llow 
low //owo expected 

ответ

1

Если вы используете предпросмотр один, символы не потребляются, а анализатор пытается все позиции в строке (другими словами, он не может прыгать больше один символ за раз).

Вы можете решить эту проблему следующим образом:

(?=((?:[aeiou]+|[b-dfghj-np-tv-z]+){3}))(?:[aeiou]+|[b-dfghj-np-tv-z]+) 

demo

Теперь ведущие гласные (или согласные) потребляются для каждого матча (за пределами опережающего просмотра).

+0

Так эта часть '(?: [AEIOU] + | [б-dfghj-np- tv-z] +) 'заставит двигатель потреблять группу воялей или согласных перед сопоставлением следующей группы cvc или vcv. Кажется, я понял. Вопрос: лучше ли работать с согласными так, как вы это делали (явно указывая их) против того, как я это сделал (говоря, что это все, но не гласные)? – tigrou

+0

@tigrou: Я не думаю, что есть большая разница. –

0

Поставив все шаблоны в часть обзора, вы делаете это не жадным при выборе начальной точки совпадения. Используйте один явный и два опережения последовательности V/C вместо:

r = re.compile('(?:([aeiouy]+)(?=([^aeiouy]+[aeiouy]+)))|(?:([^aeiouy]+)(?=([aeiouy]+[^aeiouy]+)))') 

Тогда просто сцепить группам

map (lambda l:''.join(l), re.findall(r,"Helloworld"))