¿Cómo puedo hacer que aparezcan cotizaciones cuando uso AWK para buscar y reemplazar?

¿Cómo puedo hacer que aparezcan cotizaciones cuando uso AWK para buscar y reemplazar?

Actualmente estoy usando AWK para buscar y reemplazar una parte de las tres primeras apariciones de una cadena. La cadena tiene el formato como tal y hay muchas de estas cadenas en el archivo:

func(tempID="39849235",count='12');

Usandoeste enlace, pude encontrar un método para usar AWK para buscar y reemplazar las primeras tres instancias de la cadena. Lo cambié a lo que necesitaba que hiciera y a continuación se muestra un fragmento de mi script:

id=12349876
awk 'BEGIN {matches=0}
     matches < 3 && /.*tempID.*/ { sub(/tempID="[0-9]+"/,"tempID='"$id"'"); matches++ }
     { print $0 }' filName.py >filName.py.changed

El objetivo del código anterior es hacer coincidir cualquier línea que contenga tempID y reemplazar el número asignado a tempID con un valor contenido en una variable denominada $id. Buscar y reemplazar funciona bien, pero el único problema que parece tener es que no importa cómo lo estructure, el resultado imprime el $id sin comillas. Intenté escapar de las comillas y poner marcas simples, pero de todos modos la línea cambió a:

func(tempID=39849235,count='12');

Intenté eliminar las comillas dobles alrededor de la parte de reemplazo y estructurarla como tempID="$id", pero desafortunadamente esto solo reemplaza el número de identificación con la cadena $id.

Avíseme si hay alguna manera de encontrar y reemplazar el valor de tempID y rodear el valor entre comillas. No estoy atrapado con AWK, por lo que cualquier otro método con cualquier otra utilidad como sed también funcionaría bien.

Respuesta1

En su comando hay comillas interpretadas y eliminadas por el shell, hay comillas interpretadas y eliminadas por awk, entonces necesita comillas que sobrevivan. Deberías escapar de ellos:

id=12349876
awk 'BEGIN {matches=0}
 matches < 3 && /.*tempID.*/ { sub(/tempID="[0-9]+"/,"tempID=\"'"$id"'\""); matches++ }
 { print $0 }' filName.py >filName.py.changed              # ^^  here ^^

Explicación. Tu comando original es como

awk 'BEGIN {matches=0} matches < 3 && /.*tempID.*/ { sub(/tempID="[0-9]+"/,"tempID='"$id"'"); matches++ } { print $0 }'
#   ^ these quotes are seen by the shell and don't get to awk                      ^^   ^^                            ^
#     these quotes get to awk and serve their purpose there      ^      ^  ^              ^
#     this variable is expanded by the shell and gets to awk as its value            ^^^

Y este es el comando mejorado:

awk 'BEGIN {matches=0} matches < 3 && /.*tempID.*/ { sub(/tempID="[0-9]+"/,"tempID=\"'"$id"'\""); matches++ } { print $0 }'
#   ^ these quotes are seen by the shell and don't get to awk                        ^^   ^^                              ^
#     these quotes get to awk and serve their purpose there      ^      ^  ^                  ^
#     these quotes will appear in the output thanks to being escaped                ^        ^
#     this variable is expanded by the shell and gets to awk as its value              ^^^

Para reducir el frenesí de las citas, puede usar -vla opción para pasar la variable a awk. Entonces no necesita cerrar y volver a abrir las comillas simples a mitad de la secuencia solo para permitir que el shell se expanda $id. En cambio, sin comillas (como awkse ve) idse amplía por awksí solo. Las comillas dobles que necesitamos agregar deben tener caracteres de escape como antes:

id=12349876
awk -v id="$id" 'BEGIN {matches=0}
 matches < 3 && /.*tempID.*/ { sub(/tempID="[0-9]+"/,"tempID=\""id"\""); matches++ }
 { print $0 }' filName.py >filName.py.changed

Respuesta2

Para lograr lo que quieres hacer, necesitas:

Para comillas dobles:

  • AWK: Escape de comillas dobles "dentro de otras comillas dobles.
    $1 $2=> foobar
    $1" __"$2"__"=> foo __bar__
    $1" \""$2"\""=>foo "bar"

Para comillas simples:

  • Shell: Salga '…'de todo su script awk, usando otro conjunto de '…'dentro de él.
    'escaped 'unescaped' escaped'
    '$LINUX '$OSTYPE' $CPUTYPE'=>$LINUX linux-gnu $CPUTYPE

  • Shell: Escape 'que desea imprimir literalmente.
    'apostrophe that'\''s literal'=>apostrophe that's literal

Por ejemplo

echo foo bar | awk '{print "\""$1"\" '\''"$2"'\''"}'
"foo" 'bar'

información relacionada