csvファイルとawk:最初の列が一致した場合は、2番目の列項目を変更してファイル全体を印刷します。

csvファイルとawk:最初の列が一致した場合は、2番目の列項目を変更してファイル全体を印刷します。

私は独自のパスワードマネージャを作成しており、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つの問題が発生します。

  1. 出力に項目がありません。それがまさにmastodon;password2平和ですtest;test。私は彼らがa)同じ行にとどまり、b)そのままであることを願っています。

  2. 最後の行を変更したい場合は、常に間違っています。たとえば、これを使用すると、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

つまり、フィールドNrを変更します。 2新しいパスワードを使用し、通常は(修正可能な)行(略語1)を印刷します。このように、レコードの最後の行も正常に変更されました。

adminまた、条件を正規表現ではなく正確に一致させるのが賢明なようです。あるアカウント名に別のアカウント名と一致する文字列(たとえば、およびの文字列webadmin)を含めることができるかどうかはわかりません。

関連情報