Tutorial de Ruby – Parte 7 – Expresiones regulares

Tutorial RubyCapítulo 5. Expresiones regulares

Realicemos un programa mucho más interesante. Es el momento de comprobar si una cadena satisface una descripción, que llamaremos patrón.

En estos patrones existen algunos caracteres y combinaciones de caracteres que tienen un significado especial, y son:

Tabla 5-1. Caracteres especiales en expresiones regulares

SímboloDescripción>
[]Especificación de rango. (p.e. [a-z] representa una letra en el rango de la a a la z
\wLetra o dígito; es lo mismo que [0-9A-Za-z]
\WNi letra, ni dígito
\sEspacio, es lo mismo que [ \t\n\r\f]
\SNo espacio
\dDígito; es lo mismo que [0-9]
\DNo dígito
\bBackspace (0x08) (sólo si aparece en una especificación de rango)
\bLímite de palabra (sólo si no aparece en una especificación de rango)
\BNo límite de palabra
*Cero o más repeticiones de lo que precede
+Una o más repeticiones de lo que precede
[m,n]Al menos m y como máximo n de lo que precede
?Al menos una repetición de lo que precede; es lo mismo que [0,1]
|Puede coincidir con lo que precede o con lo que sigue
()Agrupamiento

 

El término común para esto patrones que utilizan este extraño vocabulario es expresión regular. En Ruby, como en Perl, normalmente están rodeadas por barras inclinadas en vez de por comillas dobles. Si nunca antes se ha trabajado con expresiones regulares, es probable que parezcan cualquier cosa excepto regulares, pero sería inteligente dedicar algún tiempo a familiarizarse con ellas. Tienen un poder expresivo en su concisión que puede evitar muchos dolores de cabeza (y muchas líneas de código) si se necesita realizar coincidencia de patrones o cualquier otro tipo de manipulación con cadenas de texto.

Por ejemplo, supongamos que queremos comprobar si una cadena se ajusta a esta descripción: “Comienza con una f minúscula, a la que sigue exactamente una letra mayúscula y opcionalmente cualquier cosa detrás de ésta, siempre y cuando no haya más letras minúsculas.” Si se es un experimentado programador en C probablemente se haya escrito este tipo de código docenas de veces, ¿verdad? Admitádmoslo, es difícil mejorarlo. Pero en Ruby sólamente es necesario solicitar que se verifique la cadena contra la siguiente expresión regular /^f[A-Z][^a-z]*$/.

Y que decir de “¿Contiene la cadena un número hexadecimal entre ángulos?” No hay problema.

 

ruby> def chab(s) # contiene la cadena un hexadecinal entre ángulos

ruby| (s =~ /<0[Xx][\dA-Fa-f]+>/) != nil

ruby| end

nil

ruby> chab «Este no es»

false

ruby> chab «¿Puede ser esta? (0x35)» # entre paréntesis, no ángulos

false

ruby> chab «¿O esta? <0x38z7e>» # letra errónea

false

ruby> chab «OK esta si; <0xfc0004>»

true

 

Aunque inicialmente las expresiones regulares pueden parecer enigmáticas, se gana rápidamente satisfacción al ser capaz de expresarse con tanta economía.

A continuación se presenta un pequeño programa que nos permitirá experimentar con las expresiones regulares. Almacenémoslo como regx.rb, se ejecuta introduciendo en la línea de comandos ruby regx.rb

 

# necesita un terminal ANSI!!!

 

st = «\033[7m»

en = «\033[m»

 

while TRUE

print «str> «

STDOUT.flush

str = gets

break if not str

str.chop!

print «pat> «

STDOUT.flush

re = gets

break if not re

re.chop!

str.gsub! re, «#{st}\\&#{en}»

print str, «\n»

end

print «\n»

 

El programa necesita dos entradas, una con la cadena y otra con la expresión regular. La cadena se comprueba contra la expresión regular, a continuación muestra todas las partes de la cadena que coinciden con el patrón en vídeo inverso.

No nos preocupemos de los detalles; analizaremos el código posteriormente.

 

str> foobar

pat> ^fo+

foobar

~~~

 

Lo resaltado es lo que aparecerá en vídeo inverso como resultado de la ejecución del programa. La cadena ’~~~’ es en beneficio de aquellos que usen visualizadores en modo texto.

 

Probemos algunos ejemplos más.

 

str> abc012dbcd555

pat> \d

abc012dbcd555

 

Sorprendentemente y como indica la tabla al principio de este capítulo: \d no tiene nada que ver el carácter d, sino que realiza la coincidencia con un dígito.

 

¿Qué pasa si hay más de una forma de realizar la coincidencia con el patrón?.

 

str> foozboozer

pat> f.*z

foozboozer

~~~~~~~~

 

se obtiene foozbooz en vez de fooz porque las expresiones regulares tratan de obtener la coincidencia más larga posible.

 

A continuación se muestra un patrón para aislar la hora de un campo limitada por dos puntos.

 

str> WedFeb 7 08:58:04 JST 2001

pat> [0-9]+:[0-9]+(:[0-9]+)?

WedFeb 7 08:58:04 JST 2001

~~~~~~~~

 

=~ es el operador de coincidencia con expresiones regulares; devuelve la posición en la cadena donde se ha producido una coincidencia o nil si no la hay.

 

ruby> «abcdef» =~ /d/

3

ruby> «aaaaaa» =~ /d/

nil

Otras fuentes para consultar:

  • http://rubular.com/
  • https://carlossanchezperez.wordpress.com/2013/06/30/expresiones-regulares-en-ruby-no-te-dejes-intimidar-primera-parte/
  • http://www.elwebmaster.com/general/ruby-principiantes-expresiones-regulares
  • http://linuxmanr4.com/2014/08/19/expresiones-regulares-con-ruby/
  • http://picandocodigo.net/2013/expresiones-regulares-en-ruby/

 

Video — Sesión 8. Expresiones Regulares en Ruby.

¿Tienes alguna consulta?
¿Quieres compartir algún código?

Gus Terrera

Apasionado por el agile testing y la ia.

Deja una respuesta