Bienvenidos sean a este post, hoy hablaremos sobre los reemplazos y para comenzar mencionaremos una particularidad de string.gsub, su tercer argumento no tiene que ser necesariamente una cadena ya que puede ser una funcion o una tabla.

Anuncios

Cuando se invoca una funcion string.gsub se encarga de llamarla cada vez que hay una coincidencia donde los argumentos para cada llamada son las capturas y el valor que devuelve la funcion es la que se usa para reemplazo, cuando se invoque con una tabla string.gsub mira la tabla usando la primer captura como la clave y el valor asociado es usado como cadena de reemplazo, si la tabla no tiene la clave para este caso no habra modificaciones.

Anuncios

Para nuestro primer ejemplo, la siguiente funcion hace una expansion variable: substituye el nombre de la variable global nombrevar ante cualquier coincidencia de $nombrevar en una cadena:

function expandir(s)
	return (string.gsub(s, "$(%w+)", _G))
end

nombre = "Lua"; estado = "buenisimo"
print(expandir("$nombre es $estado, no es asi?"))
Anuncios

Por cada coincidencia con ‘$(%w+)’ es decir el signo de dolar ($) seguido por un nombre hace a string.gsub mirar en la tabla _G en busqueda del nombre capturado donde en caso de encontrarlo lo reemplaza, veamos la salida del ejemplo anterior:

> print(expandir("$nombre es $estado, no es asi?"))
Lua es buenisimo, no es asi?
Anuncios

Pero en el caso de no encontrar la clave dentro de la tabla no hay reemplazo, veamos el siguiente caso:

> print(expandir("$otronombre es $estado, no es asi?"))
$otronombre es buenisimo, no es asi?
Anuncios

En este caso vemos como no existe en la tabla global _G deja el mismo nombre ($otronombre) sin reemplazarlo, y como podemos hacer si no estamos seguros si las variables informadas tiene valores asignados? una posibilidad es aplicar tostring a sus valores, para este caso podemos usar una funcion en el valor de reemplazo como se ve en el siguiente ejemplo:

function expandir(s)
	return (string.gsub(s, "$(%w+)", function(n)
		return tostring(_G[n])
	end))
end
Anuncios

Ahora para cada coincidencia con ‘$(w+)’ string.gsub llama a la funcion informada con el nombre capturado como argumento, el return reemplaza la coincidencia, si la funcion devuelve nil es porque no hubo coincidencias, con la modificacion anterior probemos con el siguiente comando:

> print(expandir("print: $print; a = $a"))
print: function: 0x4e1620; a = nil
Anuncios

Observen como nos devolvio la informacion relacionada a cada argumento que la pasamos a la funcion, para nuestro ultimo ejemplo vamos a volver a nuestro convertidor de formato visto en el post anterior, de nuevo queremos convertir comandos del estilo LaTeX (\comando{texto}) al estilo XML (<comando>texto</comando>) pero esta vez permitiendo comando anidados, para ello usaremos recursion como se ve en el siguiente codigo:

function toxml(s)
	s = string.gsub(s, "\\(%a+)(%b{})", function(tag, cuerpo)
		cuerpo = string.sub(cuerpo, 2, -2)
		cuerpo = toxml(cuerpo)
		return string.format("<%s>%s</%s>", tag, cuerpo, tag)
	end)
	return s
end
Anuncios

En este caso recibiremos una cadena, despues la procesaremos por medio de string.gsub donde pasaremos la cadena recibida y por medio de los dos patrones obtendremos primero el tag (a traves de la barra invertida y la clase que se encarga de obtener toda la palabra despues de esta), nuestro siguiente patron se encargara de obtener la palabra entre las dos llaves la cual sera cuerpo, nuestro siguiente paso sera una funcion que se encargara de enviar estos datos respectivamente, la primera linea de esta funcion se encarga de eliminar las llaves de cuerpo, despues hacemos la recursion para manejar los comandos anidados, por ultimo devolvemos el resultado final con string.format donde al igual que la vez anterior usamos a %s para cada cadena, y el orden que deben ser ubicados, una vez terminado se asigna a la variable s que contenia a string.gsub y lo devuelve, probemos con el siguiente comando:

> print(toxml("\\title{El \\bold{\\em{gran}} reemplazo}"))
<title>El <bold><em>gran</em></bold> reemplazo</title>
Anuncios

Como pueden ver en este caso no solo nos cambio el anidado base sino tambien el anidado del anidado de manera correcta.

Anuncios
Anuncios

En resumen, hasta aca la primera parte de reemplazos, hemos visto su base, como se puede mejorar, ejemplos practicos de los mismos, en el proximo post continuaremos ahondando sobre este tema, 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