Я пишу свой собственный менеджер паролей, который я хочу строго соответствовать POSIX. Для упрощения: у меня есть этот файл, file.csv
:
mastodon;password2
bla;test
test;test
posteo;tewtasdwqrr
По сути, мне нужна функция, которая принимает два аргумента: она должна выбрать первый аргумент из первого столбца и в этой строке заменить запись второго столбца вторым аргументом.
Например: f "bla" "etewtw"
изменит пароль последней записи на etewtw
.
Я попробовал использовать awk, что тоже работает:
awk -F ";" -v acc="bla" -v newpw="etewtw" \
'$1 ~ acc { $2=newpw; print $1";"$2 } END {print;} ' file.csv
В принципе, я пытался установить второй столбец в newpw
аргумент, если первый столбец совпадает с acc
аргументом. После изменения потока я хочу вывести полный поток, что не работает. Вышеприведенное решение, очевидно, не является правильным, но я не знаю, как это исправить.
Вывод:
bla;etewtw
posteo;tewtasdwqrr
Так что это своего рода успех, запись была изменена (по крайней мере в потоке, но на самом деле изменить файл несложно).
Однако возникают две проблемы:
В выводе отсутствуют записи. А именно
mastodon;password2
иtest;test
. Я ожидаю, что они а) останутся на той же строке и б) не изменятся.Если я хочу изменить последнюю строку, это всегда неправильно. Например, если я использую
awk -F ";" -v acc="posteo" -v newpw="test" '$1 ~ acc { $2=newpw; print $1";"$2 } END {print;} '
вместо этого, результат будет:
posteo;test
posteo test
а это не то, чего я хочу. Я хочу, чтобы последняя строка не отличалась от любой другой строки.
решение1
Чтобы ваше имя и пароль рассматривались как буквальные строки, вам понадобится любой из этих вариантов:
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
Вам нужен этот подход, потому что переменные передаются с помощью -v
escape-последовательностей expand. Таким образом, если любая из передаваемых вами переменных содержит обратную косую черту, например foo\tbar
, то \t
в середине будет расширен и обработан как буквальный символ табуляции.
Видетьhttp://cfajohnson.com/shell/cus-faq-2.html#Q24и/илиhttps://stackoverflow.com/questions/19075671/how-do-i-use-shell-variables-in-an-awk-scriptЧтобы получить больше информации.
решение2
Единственное изменение, которое я бы увидел необходимым, это то, что у вас есть оператор print
в END
разделе, но отсутствует один для несовпадающих строк. Вместо этого вам следует сделать следующее:
awk -F';' -v OFS=';' -v acc='bla' -v newpw='etewtw' '$1 == acc {$2=newpw}1' file.csv
т.е. просто замените поле № 2 новым паролем и в общем случае выведите (возможно, измененную) строку (сокращенное обозначение для этого — 1
). С помощью этого мне также удалось изменить запись в последней строке.
Кроме того, было бы разумно сделать условие точным совпадением вместо регулярного выражения, поскольку никогда не знаешь, может ли одно имя учетной записи содержать строку, которая совпадает с другим именем учетной записи (например, как admin
и webadmin
).