2017-01-29 1 views
0

Je voudrais écrire une regex qui divise un mot en groupes cvc (consonne/voyelle/consonne) ou vcv. Quelque chose de similaire à ngrams mais en utilisant des voyels et des consonnes. Voici un exemple:Comment extraire des groupes de consonnes/voyelles d'un mot?

helloworld 

produiraient les groupes suivants:

hell 
ello 
llow 
owo 
world 

J'ai écrit le regex suivant:

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

La première partie ([aeiouy]+|[^aeiouy]+){3} capture soit un groupe VCV ou cvc , le reste (?=()) est une assertion positive de lookahead. Il ne fonctionne pas comme prévu:

hell 
ello 
llow 
low //owo expected 

Répondre

1

Si vous utilisez un seul regard en avant, les personnages ne sont pas consommés, et l'analyseur essaie toutes les positions dans la chaîne (en d'autres termes, il est capable de sauter plus un caractère à la fois).

Vous pouvez résoudre le problème comme celui-ci:

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

demo

Maintenant, les principales voyelles (ou consonnes) sont consommées pour chaque match (en dehors du préanalyse).

+0

Ainsi, la présente partie '(? [Aeiou] + | [b-dfghj-NP- tv-z] +) 'forcera le moteur à consommer un groupe de voyels ou de consonnes avant de correspondre au prochain groupe cvc ou vcv. Je crois que j'ai compris. Question: est-il préférable de faire correspondre les consonnes comme vous l'avez fait (en les spécifiant explicitement) et comment je l'ai fait (en disant que c'est tout mais pas les voyelles)? – tigrou

+0

@tigrou: Je ne pense pas qu'il y ait une grande différence. –

0

En plaçant tous les motifs dans la partie lookahead, vous le rendez non gourmand en choisissant un point de départ. Utilisez un explicite et deux préanalyse V/séquence C à la place:

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

Ensuite, il suffit concaténer les groupes

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