数値を含むファイルがあります。
$ cat file.dat
0.092593
0.048631
0.027957
0.030699
0.026250
0.038156
0.011823
0.013284
0.024529
0.022498
0.013217
0.007105
0.018916
0.014079
現在の行と前の行の違いを含む新しいファイルを作成したいと思います。予想される出力は次のようになります。
$ cat newfile.dat
-0.043962
-0.020674
0.002742
-0.004449
0.011906
-0.026333
0.001461
0.011245
-0.002031
-0.009281
-0.006112
0.011811
-0.004837
簡単だと思うので、このコードで始めました。
f="myfile.dat"
while read line; do
curr=$line
prev=
bc <<< "$line - $prev" >> newfile.dat
done < $f
しかし、私はファイルの前の行にアクセスする方法がわからないことにすぐに気づきました。最初の行を読むときにマイナスがないことを考慮する必要があるようです。進行方法のご案内をいただきありがとうございます!
ベストアンサー1
$ awk 'NR > 1 { print $0 - prev } { prev = $0 }' <file.dat
-0.043962
-0.020674
0.002742
-0.004449
0.011906
-0.026333
0.001461
0.011245
-0.002031
-0.009281
-0.006112
0.011811
-0.004837
シェルループ呼び出し内でこれを行うのはbc
面倒です。上記は、awk
ファイルの値を1つずつ読み、最初の行以降のすべての行について説明する違いを印刷する単純なスクリプトを使用しています。
NR > 1 { print $0 - prev }
2行目以上(NR
これまでに読んだレコード数、デフォルトでは「レコード」は1行)に達すると、最初のブロックは条件付きでこの行と前の行の違いを印刷します。
2番目のブロック{ prev = $0 }
は無条件prev
に現在の行の値に設定されます。
newfile.dat
結果を保存するには、出力をリダイレクトします。
$ awk 'NR > 1 { print $0 - prev } { prev = $0 }' <file.dat >newfile.dat
関連:
誰かがbc
ループ呼び出しが遅いと述べました。以下は、シェルループからデータを読み取るときに単一の呼び出しを使用して算術を実行する方法です。bc
(私は実際にこの方法で問題を解決することをお勧めしません。coに興味がある人のためにここに表示しています。) - プロセスは次のとおりですbash
。
#!/bin/bash
coproc bc
{
read prev
while read number; do
printf '%f - %f\n' "$number" "$prev" >&"${COPROC[1]}"
prev=$number
read -u "${COPROC[0]}" result
printf '%f\n' "$result"
done
} <file.dat >newfile.dat
kill "$COPROC_PID"
の値${COPROC[1]}
は標準入力ファイル記述子ですが、標準出力ファイル記述子ではありませんbc
。${COPROC[0]}
bc