2010-09-21 8 views
7

En utilisant re en Python, je voudrais renvoyer tous les caractères dans une chaîne qui précède la première apparition d'un trait de soulignement. En outre, je voudrais que la chaîne qui est retournée soit en majuscule et sans caractères non alphanumériques.Renvoyer tous les caractères avant le premier caractère de soulignement

Par exemple:

AG.av08_binloop_v6 = AGAV08 
TL.av1_binloopv2 = TLAV1 

Je suis assez sûr que je sais comment retourner une chaîne en majuscules à l'aide string.upper() mais je suis sûr qu'il ya plusieurs façons d'éliminer le . efficacement. Toute aide serait grandement appréciée. J'apprends encore des expressions régulières lentement mais sûrement. Chaque conseil est ajouté à mes notes pour une utilisation future.

Pour plus de clarté, mes exemples ci-dessus ne sont pas les chaînes réelles. La chaîne réelle ressemblerait à ceci:

AG.av08_binloop_v6 

Avec ma sortie désirée ressembler à:

AGAV08 

Et l'exemple suivant serait le même. Chaîne:

TL.av1_binloopv2 

sortie souhaitée:

TLAV1 

Encore une fois, merci à tous pour l'aide!

Répondre

7

Essayez ceci:

re.sub("[^A-Z\d]", "", re.search("^[^_]*", str).group(0).upper()) 
+0

+1 "sur spec", regarde bien mais je ne suis pas un gourou regex. Edit: Je remplacerai 're.search' par' re.match' et laisser tomber le '^' initial dans le motif ('match' commence toujours au début de la chaîne et est optimisé pour cela). – delnan

+0

Bien que j'aime la simplicité des autres réponses, je voulais aussi que toute solution que je suis allé avec soit utile pour l'exploration de l'expression régulière. Celui-ci correspond à la facture. Merci Gumbo! – durandal

+0

Juste pour la connaissance future, comment cela serait-il fait avec '' re.compile''? J'aime la nature d'un one-liner de ceci, mais il serait bon de savoir pour la connaissance future. – durandal

19

Même sans re:

text.split('_', 1)[0].replace('.', '').upper() 
+1

Personnellement, je trouve cela plus lisible et compréhensible à première vue et préfèreraient donc lire ceci dans mon code que la réponse acceptée. – HorseloverFat

2

Vous ne devez pas utiliser re pour cela. les opérations de chaîne simples seraient assez fonction de vos besoins:

tests = """ 
AG.av08_binloop_v6 = AGAV08 
TL.av1_binloopv2 = TLAV1 
""" 

for t in tests.splitlines(): 
    print t[:t.find('_')].replace('.', '').upper() 

# Returns: 
# AGAV08 
# TLAV1 

Ou si vous devez absolument utiliser re:

import re 

pat = r'([a-zA-Z0-9.]+)_.*' 
pat_re = re.compile(pat) 

for t in tests.splitlines(): 
    print re.sub(r'\.', '', pat_re.findall(t)[0]).upper() 

# Returns: 
# AGAV08 
# TLAV1 
+0

Même si je suis d'accord que les regex ne guérissent pas le cancer et sont généralement surutilisés, ils * sont * un choix viable pour des tâches comme celle-ci. – delnan

+1

Viable, oui. Mais trop compliqué pour une tâche aussi simple. – jathanism

+0

La solution de Gumbo est un oneliner plutôt lisible. Si l'on connaît les bases de regex, il est parfaitement clair ce qu'il fait. Ce n'est pas comme si c'était un monstre de personnage de 6k. – delnan

1

import re

re .sub ("[^ AZ \ d]", "", yourstr.split ('_', 1) [0] .upper())

2

Puisque tout le monde donne leur mise en œuvre préférée, voici le mien qui n'utilise pas re:

>>> for s in ('AG.av08_binloop_v6', 'TL.av1_binloopv2'): 
...  print ''.join(c for c in s.split('_',1)[0] if c.isalnum()).upper() 
... 
AGAV08 
TLAV1 

Je mis .upper() à l'extérieur du générateur de sorte qu'il est appelée une seule fois.

2

Il, juste pour le plaisir, une autre option pour obtenir un texte avant le premier trait de soulignement est:

before_underscore, sep, after_underscore = str.partition('_') 

Donc en une seule ligne pourrait être:

re.sub("[^A-Z\d]", "", str.partition('_')[0].upper()) 
Questions connexes