Quiero canalizar la salida de un archivo de "plantilla" en MySQL, el archivo tiene variables como ${dbName}
intercaladas. ¿Cuál es la utilidad de línea de comando para reemplazar estas instancias y volcar la salida a la salida estándar?
bash
command-line
text-processing
templating
Dana la sana
fuente
fuente
cat
. Todo lo que necesita essed -e "s/\${i}/1/" -e "s/\${word}/dog/" template.text
.sed
esperará un texto escapado, lo cual es una molestia.Actualizar
Aquí hay una solución de yottatsa en una pregunta similar que solo reemplaza variables como $ VAR o $ {VAR}, y es breve.
Por supuesto, si i y word están en su entorno, entonces es solo
En mi Mac parece que se instaló como parte de gettext y de MacGPG2
Vieja respuesta
Aquí hay una mejora a la solución de mogsie en una pregunta similar, mi solución no requiere que escale las comillas dobles, lo hace mogsie, ¡pero la suya es de una sola línea!
El poder de estas dos soluciones es que solo obtienes unos pocos tipos de expansiones de shell que no ocurren normalmente $ ((...)), `...` y $ (...), aunque la barra diagonal inversa es un escapar del personaje aquí, pero no tiene que preocuparse de que el análisis tenga un error, y hace varias líneas muy bien.
fuente
envsubst
parece que lo desnudo no funciona si tus envars no se exportan.envsubst
, como su nombre lo indica, solo reconoce variables de entorno , no variables de shell . También vale la pena señalar queenvsubst
es una utilidad GNU y, por lo tanto, no está preinstalada ni disponible en todas las plataformas.Utilizar
/bin/sh
. Cree un pequeño script de shell que establezca las variables y luego analice la plantilla utilizando el propio shell. Me gusta así (edite para manejar líneas nuevas correctamente):Archivo template.txt:
Archivo script.sh:
Salida:
fuente
bash
Se ejecutará todo el comando en la entrada. Si la plantilla es: "las palabras son; rm -rf $ HOME", perderá archivos.read
comando, como está escrito, recorta los espacios en blanco iniciales y finales de cada línea y\
caracteres 'come' ., (C) solo use esto si confiar o controlar la entrada, porque las sustituciones de comandos (`…`
o$(…)
) incrustadas en la entrada permiten la ejecución de comandos arbitrarios debido al uso deeval
. Finalmente, existe una pequeña posibilidad de queecho
confunda el comienzo de una línea con una de sus opciones de línea de comandos.Estaba pensando en esto nuevamente, dado el interés reciente, y creo que la herramienta en la que estaba pensando originalmente era
m4
el macroprocesador para autotools. Entonces, en lugar de la variable que especifiqué originalmente, usaría:fuente
envsubst
para este uso simple de reemplazo / plantilla variable, como se menciona en otras respuestas.m4
es una gran herramienta, pero es un preprocesador completo con muchas más funciones y, por lo tanto, complejidad que puede no ser necesaria si simplemente desea reemplazar algunas variables.template.txt
data.sh
parser.sh
parsed_file.txt
fuente
`…`
o$(…)
) incrustadas en la entrada permiten la ejecución de comandos arbitrarios debido al uso deeval
, y la ejecución directa del código de shell debido al uso desource
. Además, las comillas dobles en la entrada se descartan silenciosamente yecho
podrían confundir el comienzo de una línea con una de sus opciones de línea de comandos.Aquí hay una función Bash robusta que, a pesar de usar
eval
, debería ser segura de usar.Todas
${varName}
las referencias de variables en el texto de entrada se expanden en función de las variables del shell de llamada.No se expande nada más : ni referencias de variables cuyos nombres no están encerrados
{...}
(como$varName
), ni sustituciones de comandos ($(...)
y sintaxis heredada`...`
), ni sustituciones aritméticas ($((...))
y sintaxis heredada)$[...]
).Para tratar a
$
como un literal,\
-escápelo; p.ej:\${HOME}
Tenga en cuenta que la entrada solo se acepta a través de stdin .
Ejemplo:
Código fuente de la función:
La función asume que no
0x1
,0x2
,0x3
, y0x4
caracteres de control están presentes en la entrada, porque esos caracteres. se usan internamente, ya que la función procesa texto , debería ser una suposición segura.fuente
eval
es bastante seguro de usar."
correctamente!)${FOO:-bar}
o solo generará algo si está configurado${HOME+Home is ${HOME}}
. Sospecho que con una pequeña extensión también podría devolver códigos de salida para las variables que faltan,${FOO?Foo is missing}
pero actualmente tldp.org/LDP/abs/html/parameter-substitution.html tiene una lista de estos si eso ayudaCrear
rendertemplate.sh
:Y
template.tmpl
:Renderice la plantilla:
fuente
$(rm -rf ~)
, lo está ejecutando como código.eval "echo \"$(cat $1)\""
Funciona genial !Aquí está mi solución con perl basada en la respuesta anterior, reemplaza las variables de entorno:
fuente
Si estás abierto a usar Perl , esa sería mi sugerencia. Aunque probablemente haya algunos expertos en sed y / o AWK que probablemente sepan cómo hacerlo mucho más fácilmente. Si tiene un mapeo más complejo con algo más que dbName para sus reemplazos, podría extender esto con bastante facilidad, pero también podría incluirlo en un script Perl estándar en ese momento.
Un breve script de Perl para hacer algo un poco más complicado (manejar múltiples teclas):
Si nombra el guión anterior como guión de reemplazo, podría usarse de la siguiente manera:
fuente
Aquí hay una manera de hacer que el shell realice la sustitución por usted, como si el contenido del archivo estuviera escrito entre comillas dobles.
Usando el ejemplo de template.txt con contenido:
La siguiente línea hará que el shell interpole el contenido de template.txt y escriba el resultado en estándar.
Explicación:
i
yword
se pasan como variables de entorno limitadas a la ejecución desh
.sh
ejecuta el contenido de la cadena que se pasa.echo "
' + "$(cat template.txt)
" + '"
'"
, "$(cat template.txt)
" se convierte en la salida decat template.txt
.sh -c
convierte en:echo "The number is ${i}\nThe word is ${word}"
,i
yword
son las variables de entorno especificadas.fuente
'$(rm -rf ~)'$(rm -rf ~)
las comillas literales en el archivo de plantilla coincidirán con las que agregó antes de su expansión.'$(echo a)'$(echo a)
. Produce'a'a
. Lo principal que está sucediendo es que lo primeroecho a
dentro de esto'
es ser evaluado, lo que puede no ser lo que esperas ya que está dentro'
, pero es el mismo comportamiento que incluir'
en una"
cadena entre comillas."
cadena entre comillas (incluido$(...)
) es el punto.${varname}
, no otras expansiones de mayor riesgo de seguridad.echo "
, seguida de una cadena de comillas dobles con los contenidos literales detemplate.txt
, seguido de otra cadena literal"
, todos concatenados en un solo argumento pasado ash -c
. Tiene razón en que'
no se puede hacer coincidir (ya que fue consumido por la capa externa en lugar de pasar a la interna), pero"
ciertamente puede, por lo que seGotcha"; rm -rf ~; echo "
podría ejecutar una plantilla que contenga .file.tpl:
script.sh:
fuente
\$(date)
while IFS= read -r line; do
comoread
comando, de lo contrario, eliminará los espacios en blanco iniciales y finales de cada línea de entrada. Además,echo
podría confundir el comienzo de una línea con una de sus opciones de línea de comandos, por lo que es mejor usarlaprintf '%s\n'
. Finalmente, es más seguro hacer comillas dobles${1}
.Sugeriría usar algo como Sigil : https://github.com/gliderlabs/sigil
Se compila en un solo binario, por lo que es extremadamente fácil de instalar en sistemas.
Luego puede hacer una línea simple como la siguiente:
Esto es mucho más seguro
eval
y más fácil que usar regex osed
fuente
cat
y usar<my-file.conf.template
en su lugar para que le désigil
un identificador de archivo real en lugar de un FIFO.Encontré este hilo mientras me preguntaba lo mismo. Me inspiró a esto (cuidado con los backticks)
fuente
$(cat file)
es$(< file)
eval echo "\"$(cat FILE)\""
pero aún puede fallar en que las comillas dobles en la entrada se descartan.`…`
o$(…)
) incrustadas en la entrada permiten la ejecución de comandos arbitrarios debido al uso deeval
.Muchas opciones aquí, pero pensé que tiraría la mía al montón. Está basado en Perl, solo se dirige a variables de la forma $ {...}, toma el archivo para procesarlo como argumento y genera el archivo convertido en stdout:
Por supuesto, no soy realmente una persona perl, por lo que fácilmente podría haber un defecto fatal (aunque funciona para mí).
fuente
Env::import();
línea; la importación está implícita enuse
. Además, sugiero no construir primero toda la salida en la memoria: simplemente use enprint;
lugar de$text .= $_;
dentro del bucle y suelte elprint
comando post-loop .Se puede hacer en bash si tienes control del formato del archivo de configuración. Solo necesita fuente (".") Del archivo de configuración en lugar de subshell. Eso garantiza que las variables se creen en el contexto del shell actual (y continúen existiendo) en lugar de la subshell (donde la variable desaparece cuando la subshell sale).
Si su archivo de configuración no puede ser un script de shell, simplemente puede 'compilarlo' antes de ejecutarlo (la compilación depende de su formato de entrada).
En su caso específico, podría usar algo como:
Luego canalice la salida de go.bash en MySQL y listo, con suerte no destruirá su base de datos :-).
fuente
go.bash
), tiene el extremo equivocado del palo: no son parte de la solución, son solo una forma de mostrar que las variables están siendo ajustado correctamenteEdición perl de archivos potencialmente múltiples, con copias de seguridad.
fuente
Querrá algo más robusto que las sugerencias actuales porque, aunque funcionan para su caso de uso limitado (por ahora), no serán suficientes para situaciones más complejas.
Necesitas un mejor renderizador. Necesitas el mejor renderizador. ¡Necesitas The Renderest!
Dado template.txt:
Hola persona}}!
Correr:
$ persona = Bob ./render template.txt
Y verás la salida
¡Hola Bob!
Escríbalo a un archivo redirigiendo stdout a un archivo:
$ persona = Bob ./render template.txt >dered.txt
Y si está renderizando un script que tiene $ {} variables que no desea interpolar, ¡The Renderest lo tiene cubierto sin tener que hacer nada más!
Continúe y obtenga su copia en https://github.com/relaxdiego/renderest
fuente