2009-06-27 6 views
4

est-il un moyen de correspondre à un modèle (e\d\d) plusieurs fois, capturant chacun dans un groupe? Par exemple, étant donné la chaîne ..Regex et une séquence de motifs?

blah.s01e24e25 

..Je souhaitent obtenir quatre groupes:

1 -> blah 
2 -> 01 
3 -> 24 
4 -> 25 

La regex évidente à utiliser est (en Python regex:

import re 
re.match("(\w+).s(\d+)e(\d+)e(\d+)", "blah.s01e24e25").groups() 

. .mais je veux aussi faire correspondre l'un des éléments suivants:

blah.s01e24 
blah.s01e24e25e26 

Vous ne pouvez pas sembler faire (e\d\d)+, ou plutôt vous pouvez, mais il ne capture que la dernière occurrence:

>>> re.match("(\w+).s(\d+)(e\d\d){2}", "blah.s01e24e25e26").groups() 
('blah', '01', 'e25') 
>>> re.match("(\w+).s(\d+)(e\d\d){3}", "blah.s01e24e25e26").groups() 
('blah', '01', 'e26') 

Je veux faire en une seule regex parce que j'ai plusieurs modèles pour correspondre les noms de fichiers d'épisode TV, et ne veulent pas dupliquer chaque expression pour gérer plusieurs épisodes:

\w+\.s(\d+)\.e(\d+) # matches blah.s01e01 
\w+\.s(\d+)\.e(\d+)\.e(\d+) # matches blah.s01e01e02 
\w+\.s(\d+)\.e(\d+)\.e(\d+)\.e(\d+) # matches blah.s01e01e02e03 

\w - \d+x\d+ # matches blah - 01x01 
\w - \d+x\d+\d+ # matches blah - 01x01x02 
\w - \d+x\d+\d+\d+ # matches blah - 01x01x02x03 

..et ainsi de suite pour de nombreux autres modèles. Autre chose pour compliquer les choses - Je souhaite stocker ces expressions régulières dans un fichier de configuration, donc une solution utilisant plusieurs expressions régulières et appels de fonctions n'est pas souhaitée - mais si cela s'avère impossible, je vais juste permettre à l'utilisateur d'ajouter des expressions rationnelles simples

Fondamentalement, il est un moyen pour capturer un motif de répétition en utilisant regex?

Répondre

0

Après avoir réfléchi sur le problème, je pense avoir une solution plus simple, en utilisant des groupes nommés.

Le regex simple d'un utilisateur (ou I) pourrait utiliser est:

(\w+\).s(\d+)\.e(\d+) 

La classe d'analyse syntaxique de nom de fichier prendra le premier groupe que le nom du spectacle, deuxième comme numéro de la saison, le troisième en tant que numéro de l'épisode. Cela couvre une majorité de fichiers.

Je vais laisser quelques différents groupes nommés pour ces:

(?P<showname>\w+\).s(?P<seasonnumber>\d+)\.e(?P<episodenumber>\d+) 

Pour soutenir plusieurs épisodes, je vais prendre en charge deux groupes nommés, quelque chose comme startingepisodenumber et endingepisodenumber pour soutenir des choses comme showname.s01e01-03:

(?P<showname>\w+\)\.s(?P<seasonnumber>\d+)\.e(?P<startingepisodenumber>\d+)-(?P<endingepisodenumber>e\d+) 

Et enfin permis aux groupes nommés avec des noms correspondant à episodenumber\d+ (episodenumber1, episodenumber2 etc):

(?P<showname>\w+\)\. 
s(?P<seasonnumber>\d+)\. 
e(?P<episodenumber1>\d+) 
e(?P<episodenumber2>\d+) 
e(?P<episodenumber3>\d+) 

Il exige toujours double emploi avec éventuellement les modèles pour différentes quantités de e01 s, mais il n'y aura jamais un fichier avec deux épisodes non consécutifs (comme show.s01e01e03e04), donc en utilisant les groupes starting/endingepisodenumber devraient résoudre ce problème, et bizarre cas les utilisateurs rencontrent, ils peuvent utiliser les episodenumber\d+ noms de groupe

Cela ne répond pas vraiment à la question de séquence de motifs, mais il résout le problème qui m'a amené à le demander! (Je vais encore accepter une autre réponse qui montre comment faire correspondre s01e23e24...e27 dans une regex - si quelqu'un travaille cela!)

5

Faites-en deux étapes, l'un pour trouver tous les numéros, puis on les séparer:

import re 

def get_pieces(s): 
    # Error checking omitted! 
    whole_match = re.search(r'\w+\.(s\d+(?:e\d+)+)', s) 
    return re.findall(r'\d+', whole_match.group(1)) 

print get_pieces(r"blah.s01e01") 
print get_pieces(r"blah.s01e01e02") 
print get_pieces(r"blah.s01e01e02e03") 

# prints: 
# ['01', '01'] 
# ['01', '01', '02'] 
# ['01', '01', '02', '03'] 
1

Nombre de groupes capturés égal au nombre de groupes de parenthèses. Regardez findall ou finditer pour résoudre votre problème.

1

entre parenthèses non-groupement: (?) Asdfasdg

qui ne sont pas à apparaître: (?) Adsfasdf?

c = re.compile(r"""(\w+).s(\d+) 
         (?: 
          e(\d+) 
          (?: 
            e(\d+) 
          )? 
         )? 
       """, re.X) 

ou

c = re.compile(r"""(\w+).s(\d+)(?:e(\d+)(?:e(\d+))?)?""", re.X) 
0

Peut-être quelque chose comme ça?

def episode_matcher(filename): 
    m1= re.match(r"(?i)(.*?)\.s(\d+)((?:e\d+)+)", filename) 
    if m1: 
     m2= re.findall(r"\d+", m1.group(3)) 
     return m1.group(1), m1.group(2), m2 
    # auto return None here 

>>> episode_matcher("blah.s01e02") 
('blah', '01', ['02']) 
>>> episode_matcher("blah.S01e02E03") 
('blah', '01', ['02', '03'])