2010-09-21 24 views
7

Utilizando re en Python, me gustaría devolver todos los caracteres en una cadena que precede a la primera aparición de un guión bajo. Además, me gustaría que la cadena que se está devolviendo esté en mayúsculas y sin caracteres no alfanuméricos.Devolver todos los caracteres antes del primer guión bajo

Por ejemplo:

AG.av08_binloop_v6 = AGAV08 
TL.av1_binloopv2 = TLAV1 

Estoy bastante seguro de que sabe cómo devolver una cadena en mayúsculas utilizando string.upper() pero estoy seguro de que hay varias formas de eliminar el . eficiente. Cualquier ayuda sería muy apreciada. Todavía estoy aprendiendo expresiones regulares lenta pero seguramente. Cada consejo se agrega a mis notas para uso futuro.

Para aclarar más, mis ejemplos anteriores no son las cadenas reales. La cadena real se vería así:

AG.av08_binloop_v6 

Con mi salida deseada que parece:

AGAV08 

Y el siguiente ejemplo de ello sería la misma. Cuerda:

TL.av1_binloopv2 

salida deseada:

TLAV1 

Una vez más, gracias a todos por la ayuda!

Respuesta

7

Prueba esto:

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

+1 "en la especificación", se ve bien, pero no soy un gurú regex. Editar: reemplazaría 're.search' con' re.match' y soltaría el '^' inicial en el patrón ('match' siempre comienza al comienzo de la cadena y está optimizado para esto). – delnan

+0

Aunque me gusta la simplicidad de las otras respuestas, también quería que cualquier solución que fuera me resultara útil para una mayor exploración de expresiones regulares. Éste ajusta a la ley. Gracias Gumbo! – durandal

+0

Solo para conocimiento futuro, ¿cómo se haría esto con '' re.compile''? Me gusta la naturaleza única de esto, pero sería bueno saberlo para el futuro. – durandal

19

Incluso sin re:

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

Personalmente, creemos que este sea más legible y comprensible a primera vista, y por lo tanto, preferiría leer esto en mi código base que la respuesta aceptada. – HorseloverFat

2

Usted no tiene que utilizar para este re. operaciones de cadenas simples serían suficientes en función de sus necesidades:

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

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

# Returns: 
# AGAV08 
# TLAV1 

O si es absolutamente necesario utilizar 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

Aunque estoy de acuerdo en que las expresiones regulares no curan el cáncer y generalmente se usan en exceso, * son * una opción viable para tareas como esta. – delnan

+1

Viable, sí. Pero demasiado complicado para una tarea tan simple. – jathanism

+0

La solución de Gumbo es un delineador bastante legible. Si uno conoce los conceptos básicos de expresiones regulares, está perfectamente claro lo que hace. No es como si fuera un monstruo de 6k caracteres. – delnan

1

import re

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

2

Como todo el mundo está dando a su aplicación favorita, aquí está la mía que no utiliza 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 

puse .upper() en el exterior del generador por lo que sólo se llama una vez.

2

Él, sólo por diversión, otra opción para obtener el texto antes de que el primer subrayado es:

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

Así que, en una línea podría ser:

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