Awk printfコマンドで出力を正しくフォーマットする方法は?

次のファイルがあります:

echo filename dfT08r352|30.5|2010/06/01|2016/08/29|2281|6.24503764544832|74.9404517453799| zm00dr121|37|2008/03/05|2011/09/12|1285.95833333333|3.52076203513575|42.249144421629| ccvd00121|41.6|2008/03/05|2012/03/05|1461|4|48| sddf00121|39.6|2008/03/05|2012/09/10|1649.95833333333|4.51733972165184|54.208076659822| fttt00121|41|2008/03/05|2013/09/16|2020.95833333333|5.53308236367785|66.3969883641342| ghhyy0121|42.2|2008/03/05|2014/03/18|2203.95833333333|6.03410905772302|72.4093086926762| 

このファイルをフォーマットしようとしていますawk printfを使用して、次の目的の形式にします。

  1. フィールドの順序を同じにします(左->右)
  2. コンマ “、” FS
  3. l 最後の3つのフィールド($ 5、$ 6、$ 7)の場合のみ、すべての数字が4桁になります。 0123.12や1234.10のように、先行ゼロが少なく、ポイントの後に2桁しかない場合

次のawkコマンドを記述しました

awk -F"|" "{print $1","$2","$3","$4}{format = "%04.2f,%04.2f,%04.2f,"}{printf format, $5,$6,$7}" filename 

ただし、以下の出力には次の問題があります。

  1. 順序が正しくありません(左->右)

  2. 先行ゼロがありません

    dfT08r352,30.5,2010/06/01,2016/08/29 2281.00,6.25,74.94,zm00dr121,37,2008/03/05,2011/09/12 1285.96,3.52,42.25,ccvd00121,41.6,2008/03/05,2012/03/05 1461.00,4.00,48.00,sddf00121,39.6,2008/03/05,2012/09/10 1649.96,4.52,54.21,fttt00121,41,2008/03/05,2013/09/16 2020.96,5.53,66.40,ghhyy0121,42.2,2008/03/05,2014/03/18 

誰かが私の間違いとその修正方法を教えてもらえますか?

コメント

  • FYI、各コンマを引用せずにコンマを区切るには、'BEGIN {OFS=","}'または単に

—しかし、それでは'より広範な質問に答えることはできません。

回答

フィールドは正しい順序になっていますが、最初のprintステートメントで改行(出力レコードセパレーター)が追加されているため、データはそこにありますが、予期せずラップされています。

2番目の問題は、printfに幅4を使用するように指示していることです。これには、小数点とその後の2桁が含まれ、先頭の桁には1つだけが残り、パディングには何も残されません。幅として5を使用して、データが合計4つの数値まで埋め込まれるようにしてください。小数点のが必要な場合は、代わりに幅を7に変更します。

これは、プログラムから、自分が思うものを出力するものに変更した最短の変更です。必要なもの:

awk -F"|" "{ format = "%05.2f,%05.2f,%05.2f"; print $1","$2","$3","$4"," sprintf(format, $5,$6,$7)}" filename 

複数の{ }ブロックを1つに結合し、printステートメントも1つに結合しました。

awkステートメントを最初から作成する場合は、次のようにします。

awk -v FS=\| -v OFS=, "{ $5=sprintf("%05.2f", $5); $6=sprintf("%05.2f", $6); $7=sprintf("%05.2f", $7); print $1,$2,$3,$4,$5,$6,$7}" filename 

入力フィールドセパレーターを明示的に設定します。 、出力フィールドセパレータは、各フィールドを独自に明示的に変換してから、OFSで区切られた目的のフィールドを出力します。

コメント

  • うわー!!!これは素晴らしいことで、私はたくさんのことを学びます。時間と有益な説明に本当に感謝します:)最高です!

回答

そのための1つの方法:

awk -F \| -v OFS=, "{ NF--; for(i = NF-2; i <= NF; i++) $i = sprintf("%07.2f", $i) } 1" filename 

コメント

  • @佐藤桂、Tnxは、完璧に機能します。それを理解するために、スクリプトに説明してください。私はAwkが初めてです。スクリプトのこの部分の説明のみが必要です:{NF–; for(i = NF-2; i < = NF; i ++)$ i = sprintf("%07.2f "、$ i)} 1 '

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です