Yod*_*oda 5 scripting bash shell-script
我有一个包含一些数字的文件
$ 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
Run Code Online (Sandbox Code Playgroud)
我想创建一个新文件,其中包含当前行与前一行的差异。预期输出应该是
$ 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
Run Code Online (Sandbox Code Playgroud)
认为这是微不足道的,我从这段代码开始
f="myfile.dat"
while read line; do
curr=$line
prev=
bc <<< "$line - $prev" >> newfile.dat
done < $f
Run Code Online (Sandbox Code Playgroud)
但我很快意识到我不知道如何访问文件中的前一行。我想我还需要考虑到在阅读第一行时不应该进行减法。任何有关如何进行的指导表示赞赏!
Kus*_*nda 11
$ 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
Run Code Online (Sandbox Code Playgroud)
在 shell 循环调用中执行此操作bc很麻烦。上面使用了一个简单的awk脚本,它逐行读取文件中的值,对于第一行之后的任何行,它会按照您的描述打印差异。
NR > 1 { print $0 - prev }如果我们到达第二行或更远的行(NR是到目前为止读取的记录数,并且“记录”默认为一行),则第一个块有条件地打印此行与前一行之间的差异。
第二个块,{ prev = $0 },无条件地设置prev为当前行上的值。
将输出重定向到newfile.dat以将结果保存在那里:
$ awk 'NR > 1 { print $0 - prev } { prev = $0 }' <file.dat >newfile.dat
Run Code Online (Sandbox Code Playgroud)
有关的:
有人提到bc在循环中调用很慢。下面是一种使用单个调用bc来进行算术运算的方法,同时仍然在 shell 循环中读取数据(我实际上不建议以这种方式解决这个问题,我只是在这里向对 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"
Run Code Online (Sandbox Code Playgroud)
in 的值${COPROC[1]}是 的标准输入文件描述符,bc而${COPROC[0]}是 的标准输出文件描述符bc。