次のファイルがいくつかあります。
ファイル1.dat:
1 1
1 3 4
5 9 10 11
ファイル2.dat:
3 0
8 9 0
3 9 2 4
通常、より多くの行があります(各行には、前の行よりも少ない列が含まれます)。上記の例を使用して、各ファイルの行を合計するハイブリッドbash / awkスクリプトを設計しました。
出力データ:
4 1
9 12 4
8 18 12 15
スクリプトは期待どおりに動作しますが、かなり遅いです。私のコンピュータでは、それぞれ10,000行の100個のファイルを処理するのに30分以上かかります。スクリプトは、すべてのファイルからn行目を収集するのにほとんどの時間を費やしているようです。file*.dat
awkコマンドに渡して私が行うことをする方法はありますか(下記参照)?
#!/bin/bash
ROWS=$1; shift
OUT_FILE=$1; shift
IN_FILE=("$@")
for i in `seq 1 1 ${ROWS}`; do
# Get ith row from all input files
for j in "${IN_FILE[@]}"; do
tail -n+${i} ${j} | head -1 >> "temp.dat"
done
# Sum the rows
awk '{for (j=1;j<=NF;j++) a[j]+=$j} END {for (j in a) printf a[j] " "}' temp.dat >> ${OUT_FILE}
echo >> ${OUT_FILE}
rm temp.dat
done
上記の例に基づくスクリプトの使用法は次のとおりです。./RowSums.sh 3 out.dat file*.dat
ベストアンサー1
anypaste
とanyを使用してくださいawk
。
$ cat tst.sh
#!/usr/bin/env bash
paste "${@}" |
awk -v numFiles="$#" '{
numFldsPerFile = NF / numFiles
for ( outFldNr=1; outFldNr<=numFldsPerFile; outFldNr++ ) {
sum = 0
for ( fileNr=1; fileNr<=numFiles; fileNr++ ) {
inFldNr = outFldNr + (fileNr - 1) * numFldsPerFile
sum += $inFldNr
}
printf "%d%s", sum, (outFldNr<numFldsPerFile ? OFS : ORS)
}
}'
$ ./tst.sh file1.dat file2.dat
4 1
9 12 4
8 18 12 15
説明的な変数名と明示的なinFldNr
計算によって、それが行うことを明確にすることができることを願っています。