私は独自のパスワード マネージャーを作成していますが、厳密に POSIX に準拠したいと考えています。簡単に言うと、次のファイルがありますfile.csv
。
mastodon;password2
bla;test
test;test
posteo;tewtasdwqrr
基本的に、2 つの引数を取る関数が必要です。最初の列から最初の引数を選択し、その行から 2 番目の列のエントリを 2 番目の引数に置き換えます。
たとえば、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
基本的に、最初の列が引数と一致する場合、2 番目の列を引数に設定しようとしましたacc
。ストリームを変更した後、完全なストリームを印刷したいのですが、うまくいきません。上記は明らかに正しい解決策ではありませんが、それを修正する方法がわかりません。
出力は次のようになります。
bla;etewtw
posteo;tewtasdwqrr
つまり、これは成功であり、エントリは変更されました (少なくともストリーム内では、実際にファイルを変更することは難しくありません)。
しかし、次の 2 つの問題が発生します。
出力にエントリがありません。つまり、
mastodon;password2
と ですtest;test
。これらは、a) 同じ行に残り、b) 変更されないものと予想されます。最後の行を変更したい場合、それは常に間違っています。たとえば、
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
展開エスケープ シーケンスで渡されるためです。したがって、渡す変数のいずれかにバックスラッシュ (例 ) が含まれている場合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
および など)。