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 newpw
argumento si la primera columna coincide con el acc
argumento. 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:
Faltan entradas en la salida. Es decir
mastodon;password2
ytest;test
. Espero que a) permanezcan en la misma línea yb) no cambien.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 -v
secuencias de escape expandidas. Entonces, si cualquiera de las variables que pasa contiene una barra invertida, por ejemplo foo\tbar
, entonces la \t
del 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 print
declaración en la END
secció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 admin
y webadmin
, por ejemplo).