archivo csv y awk: cambie la entrada de la segunda columna si la primera columna coincide, imprima el archivo completo después

archivo csv y awk: cambie la entrada de la segunda columna si la primera columna coincide, imprima el archivo completo después

Estoy escribiendo mi propio administrador de contraseñas, que quiero que sea estrictamente compatible con POSIX. Para simplificar: tengo este archivo file.csv:

mastodon;password2
bla;test
test;test
posteo;tewtasdwqrr

Básicamente, quiero tener una función que tome dos argumentos: debería seleccionar el primer argumento de la primera columna y, desde esa línea, debería reemplazar la entrada de la segunda columna con el segundo argumento.

Por ejemplo: f "bla" "etewtw"cambiaría la contraseña de la última entrada a etewtw.

Intenté usar awk, que también funciona de alguna manera:

awk -F ";" -v acc="bla" -v newpw="etewtw" \
'$1 ~ acc { $2=newpw; print $1";"$2 } END {print;} ' file.csv

Básicamente, intenté establecer la segunda columna como newpwargumento si la primera columna coincide con el accargumento. Después de cambiar la transmisión, quiero imprimir la transmisión completa, lo cual no funciona. Obviamente, lo anterior no es la solución correcta, pero no sé cómo solucionarlo.

La salida es:

bla;etewtw
posteo;tewtasdwqrr

Así que es bastante exitoso, la entrada se cambió (al menos en la secuencia, pero en realidad cambiar el archivo no es difícil).

Sin embargo, surgen dos problemas:

  1. Faltan entradas en la salida. Es decir mastodon;password2y test;test. Espero que a) permanezcan en la misma línea yb) no cambien.

  2. Si quiero cambiar la última línea, siempre es incorrecto. Por ejemplo, si uso awk -F ";" -v acc="posteo" -v newpw="test" '$1 ~ acc { $2=newpw; print $1";"$2 } END {print;} 'en su lugar, el resultado es:

posteo;test
posteo test

que no es lo que quiero. Quiero que la última línea no sea diferente de cualquier otra línea.

Respuesta1

Necesita cualquiera de estos para que su nombre y contraseña sean tratados como cadenas literales:

acc='bla' newpw='etewtw' awk '
    BEGIN{FS=OFS=";"; acc=ENVIRON["acc"]; newpw=ENVIRON["newpw"]}
    $1 == acc{$2=newpw} 1
' file.csv

awk '
    BEGIN{FS=OFS=";"; acc=ARGV[1]; newpw=ARGV[2]; ARGV[1]=ARGV[2]=""}
    $1 == acc{$2=newpw} 1
' 'bla' 'etewtw' file.csv

Necesita este enfoque porque las variables se pasan con -vsecuencias de escape expandidas. Entonces, si cualquiera de las variables que pasa contiene una barra invertida, por ejemplo foo\tbar, entonces la \tdel medio se expandirá y se tratará como un carácter de tabulación literal.

Verhttp://cfajohnson.com/shell/cus-faq-2.html#Q24y/ohttps://stackoverflow.com/questions/19075671/how-do-i-use-shell-variables-in-an-awk-scriptpara más información.

Respuesta2

La única modificación que creo que es necesaria es que tenga una printdeclaración en la ENDsección, pero le falte una para las líneas que no coinciden. Lo que deberías hacer en cambio es

awk -F';' -v OFS=';' -v acc='bla' -v newpw='etewtw' '$1 == acc {$2=newpw}1' file.csv

es decir, simplemente reemplace el campo Nr. 2 con la nueva contraseña y, en general, imprima la línea (posiblemente modificada) (la notación abreviada para eso es 1). Con esto también logré cambiar el registro en la última línea.

Además, sería prudente hacer que su condición sea una coincidencia exacta en lugar de una expresión regular; nunca se sabe si un nombre de cuenta puede contener una cadena que coincida con otro nombre de cuenta (como en adminy webadmin, por ejemplo).

información relacionada