web-dev-qa-db-ja.com

awk内の配列を要約しますか?

次のコードがあります。

sum1=
sum2=    
declare -a a
echo $temp | awk '{split($0,a,","); name=a[1] ; for(i=2;i<=4;i++) sum1+=a[i] ; for(i=5;i<=7;i++) sum2+=a[i] }'

このコードは機能していません。ここで、tempは次のタイプの文字列です。

abc,1,2,3,4,5,6

実際、私はファイルからデータを解析しています。入力ファイルは次のようになります。

abc,1,2,3,4,5,6
de,3,5,7,8,4,2
xyz,6,5,3,7,8,2

私はそれを使って読んでいます

while  read temp
do
 #do something
done < sample.csv

予想される出力は次の形式です。

Name   Sum1  Sum2
abc      6    15
de      15    14
xyz     14    17 
6
user2179293

$ tempのセットアップ

まず、$temp変数が適切に設定されていることを確認してください:

$ temp="abc,1,2,3,4,5,6"
$ echo "$temp"
abc,1,2,3,4,5,6

簡単な例

私はそれを行うために次のアプローチを使用しました:

$ echo "$temp" | tr ',' '\n' | grep -v abc | awk '{sum+=$1};END{print sum}'
21

あなたの例

あなたのアプローチに関して、END{...}ブロックで蓄積した配列を出力するのを忘れていました:

$ echo "$temp" | awk '{split($0,a,","); name=a[1]
      for(i=2;i<=4;i++) sum1+=a[i] ; for(i=5;i<=7;i++) sum2+=a[i] }
      END{print sum1; print sum2}'
6
15

後で使用するために保存する

Awkには、呼び出された場所から親のシェルに結果を挿入するメソッドがないため、少し巧妙にして、その結果をBashの配列に保存する必要があります。

$ myarr=($(echo "$temp" | awk '{split($0,a,","); name=a[1]
      for(i=2;i<=4;i++) sum1+=a[i] ; for(i=5;i<=7;i++) sum2+=a[i] }
      END{ print sum1; print sum2}'))

上記はこれを行っています:

$ myarr=($(...awk command...))

これにより、sum1sum2の値が配列$myarrに保存されます。

配列$ myarrにアクセスする

それらは次のようにアクセス可能です:

$ echo "${myarr[@]}"
6 15

$ echo "${myarr[0]}"
6

$ echo "${myarr[1]}"
15
6
slm

これを試して:

$ awk -F',' 'BEGIN{OFS="\t";print "Name","Sum1","Sum2"}
                  {print $1,$2+$3+$4,$5+$6+$7}' sample.csv 
Name        Sum1 Sum2
abc         6    15
de          15   14
xyz         14   17

Bashループは必要ありません。awkですべてを実行できます。 -Fオプションを使用すると、入力フィールドの区切り文字を定義できます。この場合は,、行を明示的に分割する必要はありません。 awkはファイルを1行ずつ読み取るため、bash内のファイルを読み取る必要もありません。

BEGIN{}ブロックは、最初の行を読み取る前に実行され、ヘッダーを出力して、 出力セパレーターOFS)をタブに設定します。フィールドはすでに分離されているため、フィールド2〜4と5〜7を合計して、各行に出力するだけです。

11
terdon

bash

#!/usr/bin/env bash
printf "%-5s\t%s\t%s\n" Name Sum1 Sum2
while IFS=, read -a Arr
do
        (( Grp1 = Arr[1] + Arr[2] + Arr[3] ))
        (( Grp2 = Arr[4] + Arr[5] + Arr[6] ))

        printf "%-5s\t%d\t%d\n" ${Arr[0]} $Grp1 $Grp2

done < input.txt

出力

root@ubuntu:~# bash  parse.sh
Name    Sum1    Sum2
abc     6       15
de      15      14
xyz     14      17

配列要素の算術トリックを提供してくれた@ 1_CRに感謝します

3
Rahul Patil