Estou escrevendo meu próprio gerenciador de senhas, que desejo ser estritamente compatível com POSIX. Para simplificar: eu tenho este arquivo file.csv
:
mastodon;password2
bla;test
test;test
posteo;tewtasdwqrr
Basicamente, quero ter uma função que receba dois argumentos: ela deve selecionar o primeiro argumento da primeira coluna e, a partir dessa linha, substituir a entrada da segunda coluna pelo segundo argumento.
Por exemplo: f "bla" "etewtw"
alteraria a senha da última entrada para etewtw
.
Tentei usar o awk, que também funciona:
awk -F ";" -v acc="bla" -v newpw="etewtw" \
'$1 ~ acc { $2=newpw; print $1";"$2 } END {print;} ' file.csv
Basicamente, tentei definir a segunda coluna para o newpw
argumento se a primeira coluna corresponder ao acc
argumento. Após alterar o stream, quero imprimir o stream completo, o que não funciona. Obviamente, o que foi dito acima não é a solução correta, mas não sei como consertar isso.
A saída é:
bla;etewtw
posteo;tewtasdwqrr
Então deu certo, a entrada foi alterada (pelo menos no stream, mas na verdade alterar o arquivo não é difícil).
No entanto, surgem dois problemas:
Faltam entradas na saída. Ou seja,
mastodon;password2
etest;test
. Espero que a) permaneçam na mesma linha eb) permaneçam inalterados.Se eu quiser alterar a última linha, sempre está errado. Por exemplo, se eu usar
awk -F ";" -v acc="posteo" -v newpw="test" '$1 ~ acc { $2=newpw; print $1";"$2 } END {print;} '
, o resultado será:
posteo;test
posteo test
que não é o que eu quero. Quero que a última linha não seja diferente de qualquer outra linha.
Responder1
Você precisa de um destes itens para que seu nome e senha sejam tratados como strings literais:
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
Você precisa dessa abordagem porque as variáveis passadas com -v
sequências de escape expandidas. Portanto, se alguma das variáveis que você passar contiver uma barra invertida, por exemplo foo\tbar
, então o \t
no meio será expandido e tratado como um caractere de tabulação literal.
Verhttp://cfajohnson.com/shell/cus-faq-2.html#Q24e/ouhttps://stackoverflow.com/questions/19075671/how-do-i-use-shell-variables-in-an-awk-scriptPara maiores informações.
Responder2
A única modificação que considero necessária é que você tenha uma print
instrução na END
seção, mas falte uma para linhas não correspondentes. O que você deve fazer é
awk -F';' -v OFS=';' -v acc='bla' -v newpw='etewtw' '$1 == acc {$2=newpw}1' file.csv
ou seja, simplesmente substitua o campo Nr. 2 com a nova senha e, em geral, imprima a linha (possivelmente modificada) (a notação abreviada para isso é 1
). Com isso, também consegui alterar o registro da última linha.
Além disso, seria sensato tornar sua condição uma correspondência exata em vez de uma regex. Você nunca sabe se um nome de conta pode conter uma string que corresponda a outro nome de conta (como em admin
e webadmin
, por exemplo).