Bienvenidos sean a este post, hoy hablaremos sobre como hacer patrones mas utiles con clases de caracteres.

Anuncios

Una clase de caracter es un item en un patron que puede encontrar cualquier caracter en un conjunto especifico, por ejemplo la clase %d coincide con cualquier digito por lo tanto podemos buscar por una fecha en el formato dd/mm/aaaa con el patron «%d%d/%d%d/%d%d%d%d»:

> s = "La fecha limite es 31/12/2019, firme"
> fecha = "%d%d/%d%d/%d%d%d%d"
> print(string.sub(s, string.find(s, fecha)))
31/12/2019
>
Anuncios

La siguiente tabla lista todas las clases de caracteres disponibles:

ClaseDevolucion
.Todos los caracteres
%aLetras
%cCaracteres de control
%dDigitos
%lLetras minusculas
%pCaracteres de puntuacion
%sCaracteres de espacio
%uLetras mayusculas
%wCaracteres alfanumericas
%xDigitos hexadecimales
%zCaracteres cuya representacion es cero.
Anuncios

Una version mayuscula de estas clases representa el complemento de la misma, por ejemplo %A representa todos los caracteres que no sean letras, veamos el siguiente ejemplo:

> print(string.gsub("Hola, a-b-c!", "%A", "."))
Hola..a.b.c.    5
>
Anuncios

En este caso el 5 no es parte del resultado sino que es el segundo resultado de gsub que corresponde al numero total de sustituciones, tambien existen algunos caracteres llamados «caracteres magicos» que tienen atributos especiales cuando son usados en un patron, los caracteres magicos son:

( ) . % + - * ? [ ] ^ $
Anuncios

El caracter % trabaja como un caracter de escape para estos, por ejemplo %. coincide con el punto (.), %% coincide con el caracter % mismo, puedes usar el escape % no solo para los caracteres magicos pero tambien para otros caracteres no alfanumericos, cuando estes en duda juega seguro y pon un caracter de escape, para Lua los patrones son cadenas comunes, ellas no tienen tratamiento especial siguiendo la misma regla que otras cadenas, solo las funciones de patrones las interpretan como patrones y solo luego hace el trabajo del caracter % como un escape, para poner una comilla dentro de un patron usas la misma tecnica que usas para poner una comilla dentro de otras cadenas, por ejemplo puedes usar el caracter de escape con un ‘\’ el cual es el caracter de escape de Lua.

Anuncios

Un conjunto de caracteres te permite crear tus propias clases de caracteres, combinando diferentes clases y caracteres simples entre corchetes, por ejemplo el conjunto de caracteres ‘[%w_]’ coincide con ambos caracteres alfanumericos y guiones bajos, el conjunto de caracteres ‘[01]’ coincide solo con digitos binarios y el conjunto ‘[%[%]]’ coincide con corchetes, para contar el numero de vocales en un texto puedes escribir:

nvoc = select(2, string.gsub(texto, "[AEIOUaeiou]",""))
Anuncios

Puedes tambien incluir rangos de caracteres en un conjunto de caracteres para escribir el primero y el ultimo caracter del rango separado por un guion, rara vez se usa esta facilidad porque los rangos mas utiles estan predefinidos, por ejemplo: ‘[0-9]’ es la misma que ‘%d’ y ‘[0-9a-fA-F]’ es e equivalente a ‘%x’ sin embargo si quiere encontrar un digito octal es preferible usar ‘[0-7]’ en lugar de ‘[01234567]’, tambien puedes conseguir el complemento de cualquier conjunto de caracteres comenzando con ‘^’, por ejemplo el patron ‘[^0-7]’ encuentra cualquier caracter que no sea un digito octal y ‘[^\n]’ coincide con cualquier caracter diferente de nueva linea pero recuerda que no puede negar clases simples como su version de mayusculas ‘%S’ es mas simple que ‘[^%s]’, las clases de caracteres siguen el conjunto local actual para Lua, por lo tanto la clase ‘[a-z]’ pueden ser diferente de ‘%l’, en un lugar apropiado la ultima forma incluye letras como ‘ñ’ o ‘á’, como recomendacion deberiamos usar siempre la ultima forma, al menos que tengas una razon fuerte para hacer lo contrario, es mas simple, mas portable y mucho mas eficiente.

Anuncios

Puedes hacer patrones aun mas utiles con modificadores por repeticion y partes opcionales, los patrones en Lua ofrecen cuatro modificadores:

ModificadorDescripcion
+1 o mas repeticiones
*0 o mas repeticiones
0 o mas repeticiones tambien
?Opcional (0 o 1 repeticion)

El modificador ‘+’ coincide con uno o mas caracteres de la clase original, siempre obtendra la secuencia mas larga que coincide con el patron, por ejemplo el patron ‘%s+’ significa uno o mas letras o una palabra:

> print(string.gsub("uno, dos, tres y cuatro", "%a+","palabra"))
palabra, palabra, palabra palabra palabra       5
>
Anuncios

El patron ‘%d+’ coincide uno o mas digitos (un entero):

> print(string.match("el numero 1441 esta incluido", "%d+"))
1441
>
Anuncios

El modificador ‘*’ es similar a ‘+’ pero tambien acepta cero coincidencias de caracteres de la clase, un tipico uso es coincidir espacio opcionales entre las partes de un patron, por ejemplo para coincidir un par de parentesis vacio, tales como () o ( ) se puede usar el patron:

'%(%s*%)' 
Anuncios

El patron coincide con cero o mas espacios (los parentesis tambien tiene un significado especial en un patron, asi que debemos escaparlo con %), otro ejemplo es el siguiente patron:

'[_%a][_%w]*' 
Anuncios

Este busca coincidencias con identificadores en el programa de Lua, una secuencia que comienza con una letra o un guion bajo seguido por cero, mas guiones bajos o caracteres alfanumericos, al igual que ‘*’ el modificador ‘-‘ tambien coincide cero o mas coincidencias de caracteres de la clase original, sin embargo en lugar de coincidir con la secuencia mas larga se coincide con las mas corta, algunas veces no hay diferencias entre ‘*’ y ‘-‘ pero usualmente presentan resultados bastante diferentes, por ejemplo si intentas encontrar un identificador con el patron:

‘[_%a][_%w]-‘

Anuncios

Solo encontraras la primera letra porque ‘[_%w]-‘ siempre coincidira la secuencia vacia, vamos a suponer que queremos encontrar comentarios en un programa de C, muchas personas intentaran:

'/%*.*%*/' 
Anuncios

Esto es un «/*» seguido por una secuencia de cualquie caracter seguido por «*/», escrito con los escapes apropiados, sin embargo porque el ‘.*’ lo expande tan lejos como puede, el primer «/*» en el programa cerraria unicamente con el «*/»:

> prueba = "int x; /* x */ int y; /* y */"
> print(string.gsub(prueba, "/%*.*%*/", "<COMENTARIO>"))
int x; <COMENTARIO>     1
>
Anuncios

El patron ‘.-‘ en su lugar expandira la menor cantidad necesaria para encontrar el primer ‘*/’ y asi conseguir el resultado deseado:

> prueba = "int x; /* x */ int y; /* y */"
> print(string.gsub(prueba, "/%*.-%*/", "<COMENTARIO>"))
int x; <COMENTARIO> int y; <COMENTARIO> 2
>
Anuncios

El ultimo modificador ‘?’ coincide con un caracter opcional, como un ejemplo supongamos que queremos encontrar un entero en un texto, donde el numero podria contener un signo opcional, el patron ‘[+-]%d+’ hace el trabajo coincidiendo numeros como ‘-12′, ’23’ y ‘+1009’, la clase de caracter [+-] que coincide tanto al signo + y -, el siguiente signo ‘?’ lo convierte en opcional, a diferencia de otros sistemas en Lua un modificador puede ser aplicado a una clase de caracter, no hay forma de agrupar patrones debajo de un modificador, por ejemplo no hay patrones que coincida una palabra opcional (al menos que la palabra tenga una letra), por lo general se puede eludir esta limitacion usando alguna de las tecnicas avanzadas que veremos mas adelante, si el patron comienza con ‘^’ solo coincidira con el comienzo de la cadena dada, de forma similar si termina con ‘$’ coincidira con el final de la cadena dada, estas marcas pueden ser usadas tanto para restringir los patrones que encuentres y anclar los patrones, veamos el siguiente codigo:

if string.find(s, "^%d") then ...

Chequea si la cadena s comienza con un digito y lo chequea:

if string.find(s, "^[+-]?%d+$") then ...
Anuncios

Chequea si la cadena representa un numero entero sin otros caracteres iniciales o finales, otro item en un patron es ‘%b’ la cual coincide con cadenas balanceadas, tal item es escrito como ‘%bry’ donde x e y son dos caracteres distintivos, x actua como un caracter de apertura y la y como de cierre, por ejemplo el patron ‘%b()’ coincide las partes de la cadena que coinciden con ‘(‘ y finaliza con la respectiva ‘)’:

> s = "una linea (encerrada (entre) parentesis), oh Yeah!"
> print(string.gsub(s, "%b()", ""))
una linea , oh Yeah!    1
>
Anuncios

Tipicamente este patron es usado como ‘%b()’, ‘%b[]’, ‘%b{}’ o ‘%b<>’ pero puedes usar cualquier caracter como delimitador.

Anuncios

En resumen, hoy hemos hablado de los patrones en Lua, cuales son los bases, cuales son los magicos, como se utilizan en distintos aplicaciones, como podemos usar unos especiales, como se puede utiizar un ultimo entre delimitadores, espero les haya sido util sigueme en Twitter o Facebook para recibir una notificacion cada vez que subo un nuevo post en este blog, nos vemos en el proximo post.

Tengo un Patreon donde podes acceder de manera exclusiva a material para este blog antes de ser publicado, sigue los pasos del link para saber como.

Tambien podes donar

Es para mantenimiento del sitio, gracias!

$1.00