![ファイルの特定の列にある数値の内部書式設定[閉じる]](https://linux33.com/image/179655/%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%AE%E7%89%B9%E5%AE%9A%E3%81%AE%E5%88%97%E3%81%AB%E3%81%82%E3%82%8B%E6%95%B0%E5%80%A4%E3%81%AE%E5%86%85%E9%83%A8%E6%9B%B8%E5%BC%8F%E8%A8%AD%E5%AE%9A%5B%E9%96%89%E3%81%98%E3%82%8B%5D.png)
colを次の2桁のAmount
10進形式でフォーマットしようとしています。1000
1000.00
次のサンプルファイルがあります。
Bank|Branch|Comment|Amount|Extra1|Extra2
xyz|we||100||
xyz|we||100.1||
xyz|we|paid for inv# 34VM23-SEP-20|23459900.00||
xyz|errt||-230.0||
xyz|ss||234.78||
xyz|we|valid|990.2||
xyz|we|9922.9 paid|9922.9||
xyz|we||.9||
xyz|we||.0||
xyz|we||.00||
私はawk -F"|" '{OFS=FS}''{printf ("%.2f",$4) ; print }' test.csv
結果を得ようとしました。
0.00Bank|Branch|Comment|Amount|Extra1|Extra2
100.00xyz|we||100||
100.10xyz|we||100.1||
23459900.00xyz|we|paid for inv# 34VM23-SEP-20|23459900.00||
-230.00xyz|errt||-230.0||
234.78xyz|ss||234.78||
990.20xyz|we|valid|990.2||
9922.90xyz|we|9922.9 paid|9922.9||
0.90xyz|we||.9||
0.00xyz|we||.0||
0.00xyz|we||.00||
0.00
また、ヘッダー行を避け、元のファイルに置き換えたいと思います。正しい方向を教えてください。ありがとう
答え1
あなたのawkコードに欠陥があります。まず、変更された値$ 4とライン全体を印刷します。
正しいバージョンは次のとおりです。awk -F"|" 'NR<=1{print $0;next} {{printf($1"|" $2"|"$3"|%.2f|"$5"|"$6"\n",$4)}}' test
$ awk -F"|" 'NR<=1{print $0;next} {{printf($1"|" $2"|"$3"|%.2f|"$5"|"$6"\n",$4)}}' test
bank|Branch|Comment|Amount|Extra1|Extra2
xyz|we||100,00||
xyz|we||100,00||
xyz|we|paid for inv# 34VM23-SEP-20|23459900,00||
xyz|errt||-230,00||
xyz|ss||234,00||
xyz|we|valid|990,00||
xyz|we|9922.9 paid|9922,00||
xyz|we||0,00||
xyz|we||0,00||
xyz|we||0,00||
未変更フィールドと必要に応じて変更されたフィールドの両方を印刷する必要があります4。最初の行を未処理のままにするには、NRをテストし、変更なしでその行を印刷してから2行目にnext
進みます。
編集する元のコマンドと私のバージョンが存在する10進数を保持せずに0に設定するため、私のawkバージョンに問題がある可能性があります。これがあなたに効果があると思います。どうやら私たちの近所の人々と関係があると思います。たとえば、私のコンピュータでは234.78
。234,00
別の解決策は次のとおりです。ポール・ペダントコメントは$ 4の値を直接変更して後で印刷することです。
plonky@sd-143012:~/work$ awk -F '|' '{ {OFS=FS} if (FNR > 1) $4 = sprintf ("%.2f", $4); print; }' test
bank|Branch|Comment|Amount|Extra1|Extra2
xyz|we||100,00||
xyz|we||100,00||
xyz|we|paid for inv# 34VM23-SEP-20|23459900,00||
xyz|errt||-230,00||
xyz|ss||234,00||
xyz|we|valid|990,00||
xyz|we|9922.9 paid|9922,00||
xyz|we||0,00||
xyz|we||0,00||
xyz|we||0,00||
答え2
次のように動作する必要があります。
awk -F '|' 'FNR>1 {printf "%s|%s|%s|%.2f|%s|%s\n", $1,$2,$3,$4,$5,$6}'
すでに持ってい-F '|'
ますが、フィールド区切り文字があります。
現在の入力ファイルの入力レコード番号を使用して最初の行をスキップしたいと言いますFNR>1
。FNR
awkは行ベースのリーダーなので、次のように>1
表示されます。最初の行以降の処理。
を使用することも正しいですが、printf
構文が望む結果を得ることはできません。要件に応じてライン全体を印刷するように拡張できます。
また、行末の行戻りを忘れた\n
ため、奇妙なレイアウトが作成されました。
答え3
そしてミラー
mlr --csvlite --fs '|' put '$Amount = fmtnum($Amount,"%.2f")' file
ファイルを変更するには、-I
コマンドラインスイッチを追加してください。
答え4
Rakuを使う(古いPerl6)
split
明示的な呼び出しと呼び出しを介して非常に機械的な操作を実行するためにRakuを使用することもできますjoin
。このようにして、同じ数値書式コードを使用して別の列区切り記号(コンマなど)に変更できます。
~$ raku -e 'for lines.skip(1) {my @a = .split("|"); .subst(@a[3], sprintf( "%.2f", @a[3] )).join("|").put };'
tmp
また、最初にヘッダーを保存してから、書式設定されたデータ行を追加するファイルを作成するコードを作成しました。あなたが要求したわけではありませんが、うまくいきます。また、このコードを使用すると、書式設定したい列に加えて、1行あたりの合計列数を知る必要がなくなります。
一緒に入れてください:
~$ raku -e '.say for lines[0];' < bank.txt > tmp
~$ raku -e 'for lines.skip(1) {my @a = .split("|"); .subst(@a[3], sprintf( "%.2f", @a[3] )).join("|").put };' < bank.txt >> tmp
出力:
Bank|Branch|Comment|Amount|Extra1|Extra2
xyz|we||100.00||
xyz|we||100.10||
xyz|we|paid for inv# 34VM23-SEP-20|23459900.00||
xyz|errt||-230.00||
xyz|ss||234.78||
xyz|we|valid|990.20||
xyz|we|9922.90 paid|9922.9||
xyz|we||0.90||
xyz|we||0.00||
xyz|we||0.00||
HTH。