Anuncios

Bienvenidos sean a este post, hoy hablaremos sobre las funciones mas poderosas de esta tabla como son:

  • find
  • match
  • gsub (sustitucion global)
  • gmatch (encaje global)
Anuncios

Todas ellas estan basadas en patrones, a diferencia de muchos otros lenguajes no usa ni POSIX (regexp) ni las expresiones regulares de Perl para coincidir patrones, la principal decision es el tamaño porque una tipica implementacion de expresiones comunes de POSIX lleva mas de 4000 lineas de codigo, esto es aproximadamente el tamaño de todas las librerias estandar de Lua, en comparacion la implementacion de coincidencia de patrones en Lua tiene menos de 500 lineas.

Anuncios

Por supuesto, la coincidencia de patrones en Lua no puede hacer todo lo que hace una implementacion completa de POSIX, sin embargo en Lua sigue siendo una herramienta muy poderosa e incluye algunas caracteristicas que son dificiles de coincidir con las implementaciones estandard de POSIX.

Anuncios

La funcion string.find

Esta funcion busca por un patron dentro de una cadena informada, la forma mas simple de un patron es una palabra, la cual solo coincide con solo una copia de si mismo, por ejemplo el patron ‘hola’ sera buscado como una subcadena dentro de la cadena informada, cuando find encuentra su patron devuelve dos valores, el indice donde la coincidencia comienza y el indice donde termina, si no encuentra ninguna coincidencia devuelve un valor nil:

s = "Hola mundo"
i, f = string.find(s, "Hola")
print(i, f)				-- Devuelve 1	4
print(string.sub(s, i, f))		-- Devuelve Hola
print(string.find(s, "mundo"))		-- Devuelve 6	10
i, f = string.find(s, "l")
print(i, f)				-- Devuelve 3	3
print(string.find(s, "lll"))		-- Devuelve nil
Anuncios

Cuando una coincidencia es exitosa podemos llamar a string.sub con los valores devueltos por string.find para conseguir la parte de la cadena que coincida con el patron, para patrones simples este es el patron mismo, la funcion string.find tiene un tercer parametro opcional: un indice que dice desde donde comenzar la busqueda en la cadena, este parametro es util cuando queremos procesar todos los indices donde un patron dado aparece, buscamos por una nueva coincidencia repetidamente y cada vez comenzando desde la posicion donde encontramos al previo, como un ejemplo el siguiente codigo hace una tabla con las posiciones de todas las nuevas lineas en una cadena:

local t = {}
local i = 0
while true do
	i = string.find(s, "\n", i + 1)
	if i == nil then break end
	t[#t + 1] = i
end
Anuncios

En este caso tendremos a t como la tabla que usaremos para almacenar los valores, i que contendra el valor obtenido por find, dentro del bucle en la linea de string.find usaremos este argumento opcional donde sera el valor de incrementado en 1, el cual sera la nueva posicion, despues tendremos un condicional donde verifica que i sea igual a nil si es verdad corta el bucle y sale del mismo, en caso contrario sigue incrementando la tabla t, mas adelante veremos una forma mas simple para este bucle por medio del iterador gmatch.

Anuncios

La funcion string.match

Esta funcion es similar a la anterior en el sentido de que tambien busca por un patron en una cadena, sin embargo en lugar de devolver la posicion donde encontro el patron devuelve la parte de la cadena que coincidio con el patron:

print(string.match("Hola, Mundo", "Hola"))     -- Devuelve Hola
Anuncios

Para patrones fijos como ‘Hola’ esta funcion no tiene sentido porque en realidad muestra su poder cuando es usado con patrones variables como en el siguiente ejemplo:

dia = "31/10/2019"
d = string.match(dia, "%d+/%d+/%d")
print(d)				-- Devuelve 31/10/2019

En otro post hablaremos del significado del patron %d+/%d+/%d y usos mas avanzados de esta funcion.

Anuncios

La funcion string.gsub

Esta funcion tiene tres parametros, la cadena a trabajar, el patron y la cadena de reemplazo, como se daran cuenta su funcion basica es substituir a la cadena de reemplazo para todas coincidencias con el patron dentro de la cadena informada:

> s = string.gsub("Lua es lindo", "lindo", "buenisimo")
> print(s)
Lua es buenisimo
> s = string.gsub("all lii","l","x")
> print(s)
axx xii
> s = string.gsub("Lua es buenisimo","Sol","Sun")
> print(s)
Lua es buenisimo
>
Anuncios

Tambien disponemos de un cuarto parametro opcional para limitar el numero de sustituciones que se puedan hacer:

> s = string.gsub("all lii","l","x",1)
> print(s)
axl lii
> s = string.gsub("all lii","l","x",2)
> print(s)
axx lii
>

Esta funcion tambien devuelve como un segundo resultado el numero de veces que se hizo la sustitucion, por ejemplo una manera facil de contar el numero de espacio en una cadena es:

contar = select(2, string.gsub(str, " ", " "))
Anuncios

La funcion string.gmatch

Esta funcion devuelve una funcion que itera sobre todas las coincidencias de un patron en una cadena, por ejemplo el siguiente ejemplo colecciona todas las palabras de una cadena informada llamada s:

palabras = {}
for p in string.gmatch(s, "%a+") do
	palabras[#palabras + 1] = p
end
Anuncios

El patron “%a+” busca coincidencias de uno o mas caracteres alfabeticos (mas conocidos como palabras) asi que el bucle for iterara sobre todas las palabras de la cadena informada y almacenandolas en la lista palabras, del patron hablaremos mas profundamente en el proximo post, gracias a gmatch y gsub nos facilita emular en Lua la estrategia de busqueda que require usa cuando busca por los modulos, veamos el siguiente codigo:

function buscar()
	nombremod = string.gsub(nombremod, "%.", "/")
	for c in string.gmatch(path, "[^;]+") do
		local fnombre = string.gsub(c, "?", nombremod)
		local f = io.open(fnombre)
		if f then
			f:close()
			return fnombre
		end
	end
	return nil
end
Anuncios

El primer paso sera sustituir el separador de directorios, asumimos para este ejemplo que sera “/”, por cualquier punto (mas adelante veremos que el punto tiene un significado especial en los patrones y por ello usamos el patron especial %.), luego la funcion loopea sobre todos los componentes del path donde cada componente es una expansion maxima de caracteres sin punto y coma, por cada componente reemplaza el nombre del modulo por el signo de interrogacion para conseguir el nombre final y luego chequea si hay tal archivo, si es asi la funcion cierra el archivo y devuelve su nombre.

Anuncios

En resumen, hoy hemos visto las funciones encargadas de la coincidencias de patrones, como son, sus estructuras, para que se usan, cuales son sus alcances y como poder utilizarlas correctamente, 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