| You are here: Inicio > Inmersión en Python > Expresiones regulares > Caso de estudio: direcciones de calles | << >> | ||||
Inmersión en PythonPython de novato a experto |
|||||
Esta serie de ejemplos la inspiró un problema de la vida real que surgió en mi trabajo diario hace unos años, cuando necesité limpiar y estandarizar direcciones de calles exportadas de un sistema antiguo antes de importarlo a un nuevo sistema (vea que no me invento todo esto; es realmente útil). Este ejemplo muestra la manera en que me enfrenté al problema.
>>> s = '100 NORTH MAIN ROAD' >>> s.replace('ROAD', 'RD.')'100 NORTH MAIN RD.' >>> s = '100 NORTH BROAD ROAD' >>> s.replace('ROAD', 'RD.')
'100 NORTH BRD. RD.' >>> s[:-4] + s[-4:].replace('ROAD', 'RD.')
'100 NORTH BROAD RD.' >>> import re
>>> re.sub('ROAD$', 'RD.', s)
![]()
'100 NORTH BROAD RD.'
Siguiendo con mi historia de adecentar las direcciones, pronto descubrí que el ejemplo anterior que se ajustaba a 'ROAD' al final de las direcciones, no era suficientemente bueno, porque no todas las direcciones incluían la indicación del tipo de calle; algunas simplemente terminaban en el nombre de la calle. La mayor parte de las veces, podía pasar con eso, pero si la calle se llamaba 'BROAD', entonces la expresión regular coincidiría con el 'ROAD' del final de la cadena siendo parte de 'BROAD', que no es lo que yo quería.
>>> s = '100 BROAD' >>> re.sub('ROAD$', 'RD.', s) '100 BRD.' >>> re.sub('\\bROAD$', 'RD.', s)'100 BROAD' >>> re.sub(r'\bROAD$', 'RD.', s)
'100 BROAD' >>> s = '100 BROAD ROAD APT. 3' >>> re.sub(r'\bROAD$', 'RD.', s)
'100 BROAD ROAD APT. 3' >>> re.sub(r'\bROAD\b', 'RD.', s)
'100 BROAD RD. APT 3'
| Lo que yo quería de verdad era una coincidencia con 'ROAD' cuando estuviera al final de la cadena y fuera una palabra en sí misma, no parte de una mayor. Para expresar esto en una expresión regular, usamos \b, que significa “aquí debería estar el límite de una palabra”. En Python, esto se complica debido al hecho de que el carácter '\' ha de escaparse si está dentro de una cadena. A veces a esto se le llama la plaga de la barra inversa, y es una de las razones por las que las expresiones regulares son más sencillas en Perl que en Python. Por otro lado, Perl mezcla las expresiones regulares con el resto de la sintaxis, de manera que si tiene un fallo, será difícil decidir si es a causa de la sintaxis o de la expresión regular. | |
| Para evitar la plaga de la barra inversa, puede usar lo que se denominan cadenas sin procesar[3], prefijando una letra r a la cadena. Esto le dice a Python que nada de esa cadena debe ser escapado; '\t' es un carácter de tabulador, pero r'\t' es en realidad el carácter de la barra \ seguido de la letra t. Le recomiendo que siempre use estas cadenas cuando trabaje con expresiones regulares; de otro modo, las cosas pueden volverse confusas rápidamente (y las expresiones regulares ya se vuelven confusas suficientemente rápido por sí mismas). | |
| *suspiro* Desafortunadamente, pronto encontré más casos que contradecían mi lógica. En este caso, la dirección de la calle contenía la palabra 'ROAD' por separado, pero no estaba al final, ya que la dirección incluía un número de apartamento tras la indicación de la calle. Como 'ROAD' no estaba justo al final de la cadena, no había coincidencia, de manera que la invocación a re.sub acababa por no reemplazar nada, y obtenía la cadena original, que no es lo que deseaba. | |
| Para resolver este problema, eliminé el carácter $ y añadí otro \b. Ahora la expresión regular dice “busca una 'ROAD' que sea una palabra por sí misma en cualquier parte de la cadena”, ya sea al final, al principio, o en alguna parte por en medio. |
[3] raw strings
<< Expresiones regulares |
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | |
Caso de estudio: números romanos >> |