行の特定の値を合計しますが、そのフィールドのいずれかが空の場合、合計は印刷されません。

行の特定の値を合計しますが、そのフィールドのいずれかが空の場合、合計は印刷されません。

3つの列(区切り記号はカンマ)で構成されるファイルがあります。最初の列にはIDが含まれ、2番目と3番目の列には合計したい値が含まれています。合計は、出力のファイルに4番目の列として追加する必要があります。

ただし、場合によっては、3番目の列が空になることがあります(入力ファイルの2行目など)。この場合、合計に関連する列は空でなければなりません。ただし、フィールドが明示的に表示されている場合は、0合計は通常どおりに計算する必要があります(たとえば、入力ファイルの4行目)。

  • 入力.txt
    2309,-0.3,0.2
    2311,1.2,
    2312,0,-1
    2315,2.2,0
    
  • 希望の出力:
    2309,-0.3,0.2,-0.1
    2311,1.2,,
    2312,0,-1,-1
    2315,2.2,0,2.2
    

以前は同様の議論を見たことがありますが、2番目と3番目の列の間で合計を計算する必要があることを指定する方法と、3番目の列が空の行の合計をスキップする方法を知りません。以下のスクリプトは、同じ行(またID??)に含まれるすべての値を合計するようになっていますが、どういうわけか変更できますか?それとも他のより速い方法を提案してもらえますか?

NF++; $NF=sum
awk -v OFS=, -F, 'NR>1{sum=0; for(i=1; i<=NF; i++) sum += $i; NF++; $NF=sum } 1'

答え1

$ awk 'BEGIN{FS=OFS=","} {print $0, ($3=="" ? "" : $2+$3)}' input.txt
2309,-0.3,0.2,-0.1
2311,1.2,,
2312,0,-1,-1
2315,2.2,0,2.2

答え2

$ cat dst
2309,-0.3,0.2,-0.1
2311,1.2,,
2312,0,-1,-1
2315,2.2,0,2.2
$ cat awkscript
#!/bin/sh
awk -F, '
    {
        if ($3 == "") $0 = $0 ","
        else $0 = $0 "," $2+$3
        print $0
    }
' $1 >$2
$  ./awkscript src dst
$ cat dst
2309,-0.3,0.2,-0.1
2311,1.2,,
2312,0,-1,-1
2315,2.2,0,2.2

答え3

これは次の手順を使用してawk可能です。

awk 'BEGIN{FS=OFS=","} {sum=0; for (i=2;i<=NF;i++) {if ($i=="") {sum=""; break}; sum+=$i}; $(NF+1)=sum}1' input.txt 

これは

  • 入力フィールドと出力フィールドの区切り記号(FSおよびOFS)を次のように設定します。,
  • 各行に対してsum変数をリセットし0、フィールド2で始まるすべてのフィールドを合計します。ただし、フィールドが明示的に空の場合($i=="")は、合計ループから外れて空のsum文字列に設定されます。
  • sum次に、新しい追加フィールドを(実際の合計または空の文字列)値に設定します。
  • 最後に、すべての修正を含む現在の行を印刷します。これは1ルールブロックの外で「さまよう」と思われます。awkルールブロックの外側に「true」と評価されるブール条件がある場合、現在の行が印刷されます。

入力例の場合、出力は次のようになります。

2309,-0.3,0.2,-0.1
2311,1.2,,
2312,0,-1,-1
2315,2.2,0,2.2

答え4

mlr代わりにMiller()を使用してくださいawk

$ mlr --csv -N put 'is_not_empty($3) { $4 = $2 + $3 }' then unsparsify file
2309,-0.3,0.2,-0.100000
2311,1.2,,
2312,0,-1,-1
2315,2.2,0,2.200000

これにより、null以外の3番目のフィールドを持つすべてのレコードに4番目のフィールドが作成されます。unsparsifyこれにより、前のステップでフィールドが生成されなかったすべてのレコードに欠落している4番目のフィールドが生成されます。

関連情報