Estoy intentando insertar texto variable después de otro texto variable en una línea específica. A continuación se muestra mi intento hasta el momento, hasta donde puedo decir, si puedo escapar de las comillas awk
para que la variable pueda verse y aún aplicarse, entonces debería funcionar, pero no tengo idea de cómo hacerlo:
#!/bin/sh
VAR=$(head -n1 ~/Scripts/tmp/file.txt)
VAR1=$(head -n1 ~/Scripts/tmp/file1.txt)
awk '/$VAR/ { print; print "$VAR1"; next }1' ~/Scripts/tmp/file.txt
Respuesta1
Para pasar cadenas a un script awk, páselas a través de variables de entorno.
export VAR VAR1
awk '
1
$0 == ENVIRON["VAR"] {print ENVIRON["VAR1"]}
' ~/Scripts/tmp/file.txt
Reorganicé tu guión para simplificar la lógica. También reemplacé la coincidencia de expresiones regulares por una comparación de cadenas: con la coincidencia de expresiones regulares, $VAR
se trataría como una expresión regular, no realizaría una comparación de cadenas. Y /$VAR/
ni siquiera usaría el valor de VAR
(esa es la sintaxis de Perl, no awk), que necesitarías match($0, VAR)
para eso.
Una nota sobre algunas otras soluciones que realmente no funcionan (sólo funcionan si las variables no contienen ningún carácter especial, qué carácter es especial depende del método):
awk -v awkvar="$VAR" '$0 == awkvar …'
expande las barras invertidas en el contenido de la línea.awk "/$VAR/" …
hace que el shell expanda el valor deVAR
como un fragmento de awk. Por ejemplo, sifile.txt
contiene^/ {system("touch ~/naughty")} /
entonces se ejecuta el comandotouch ~/naughty
.
Un enfoque alternativo es hacer que awk lea todos los archivos.
awk '
BEGIN { VAR1 = getline <"~/Scripts/tmp/file1.txt"; }
NR == 1 {VAR = $0}
1
$0 == ENVIRON["VAR"] {print ENVIRON["VAR1"]}
' ~/Scripts/tmp/file.txt
Respuesta2
Una posible solución AWK:
awk '/'$VAR'/ { print; print "'$VAR1'"; next }1'
rompa las 'comillas alrededor de todas sus variables externas.
Otra posible solución, como la que sugiere la otra publicación, al pasar variables es pasar VAR1 como una variable awk, pero creo que aún necesitas hacer el escape del bloque de comillas simples para el patrón usando VAR:
awk -v var=$VAR1 '/'$VAR'/ { print; print var; next }1'
Podrías probar con sed en su lugar :) está diseñado específicamente para este tipo de sustitución.
sed "s/$VAR.*/\0\n$VAR1/" ~/Scripts/tmp/file.txt
Si puede tener varias instancias de VAR en una sola línea, agregue g al final del comando sed (global) para que no se detenga en la primera coincidencia que encuentre:
sed "s/$VAR.*/\0 $VAR1/g" ~/Scripts/tmp/file.txt
¡IMPORTANTE!: asegúrese de que el carácter '/' no aparezca en la variable VAR o VAR1, si pueden, necesita escaparlos para awk o sed, alternativamente con sed puede cambiar el delimitador del comando a algo como '; ' Por ejemplo:
sed "s;$VAR.*;\0\n$VAR1;" ~/Scripts/tmp/file.txt
Explicación del comando sed:
Usamos comillas dobles" en lugar de comillas simples alrededor del comando sed para que variables como VAR y VAR1 sean reemplazadas por sus valores. Esto sucede antes de que sed ejecute el comando, por lo que si / can estar presente en el contenido variable que necesita para abordarlo (esto también es cierto para awk)
La 's' indica que está escribiendo un comando de sustitución de la forma:
s/<patrón>/<patrón de reemplazo>/
El '/ 'inmediatamente después de la s está el delimitador que se usará para separar las secciones del comando, por lo que si coloca ; debe usar ; en todas partes como se muestra arriba. El patrón es \0, lo que significa imprimir lo que coincide con el patrón, una nueva línea '\n' y el contenido de VAR2.
Vaya, no vi la parte sobre la línea a continuación... patrones fijos.
Respuesta3
Si desea utilizar awk
, debe pasar la bash
variable a awk
con la -v
opción:
awk -v v=$VAR -v v1=$VAR1 '/v/ { print; print v1; next }1' ~/Scripts/tmp/file.txt
Pero consulte la respuesta de Rob para obtener una solución más correcta y detallada.