次のコードがあります。
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
まず、$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...))
これにより、sum1
とsum2
の値が配列$myarr
に保存されます。
それらは次のようにアクセス可能です:
$ echo "${myarr[@]}"
6 15
$ echo "${myarr[0]}"
6
$ echo "${myarr[1]}"
15
これを試して:
$ 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を合計して、各行に出力するだけです。
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に感謝します