我通常使用Excel完成此操作,但在我尝试学习bash时,我想在此处征求有关如何操作的建议。我的输入文件类似于:
@ s0 legend "1001"
@ s1 legend "1002"
@target G0.S0
@type xy
2.0 -1052.7396157664
2.5 -1052.7330560932
3.0 -1052.7540013664
3.5 -1052.7780321236
4.0 -1052.7948229060
4.5 -1052.8081313831
5.0 -1052.8190310613
&
@target G0.S1
@type xy
2.0 -1052.5384564253
2.5 -1052.7040374678
3.0 -1052.7542803612
3.5 -1052.7781686744
4.0 -1052.7948927247
4.5 -1052.8081704241
5.0 -1052.8190543049
&
其中上面只显示两个数据集:s0和s1。实际上我有17个数据集并将它们任意组合。通过组合,我的意思是我想:
注意:$ C乘以非常小的数字,唯一可以让它除以零的方法就是大规模。
编辑:在提出请求后,我显然不完全清楚自己的目标。举个例子:
set0
2 x
3 y
4 z
set1
2 r
3 s
4 t
我也定义了一个常数C。
我想执行以下操作:
C*(r - x)
C*(s - y)
C*(t - z)
我将为套装>做这个1,最多16,例如(设置10)减(设置0)。因此,我需要灵活地根据其行号和列号来定位值,并且最好在一系列行号上起作用,以使其有效。
到目前为止,这有效:
C=$(echo "scale=45;x=(small numbers)*(small numbers); x" | bc -l)
sed -n '5,11p' input.in | cut -c 5-20 > tmp1.in
sed -n '15,21p' input.in | cut -c 5-20 > tmp2.in
pr -m -t -s tmp1.in tmp2.in > tmp3.in
awk '{printf $2-$1 "\n"}' tmp3.in > tmp4.in
但乘法失败:
awk '{printf "%11.2f\n", "$C"*$1 }' tmp4.in > tmp5.in
返回:
0.00
0.00
0.00
0.00
0.00
0.00
0.00
我觉得用awk可以更加优雅地完成整个事情。我也试过这个:
for (( i=0; i<=6; i++ ))
do
n=5+$i
m=10+n
awk 'NR==n{a=$2};NR==m{b=$2} {printf "%d\n", $b-$a}' input.in > temp.in
done
但我得到的所有temp.in都是0列的长列。
我也试过
awk 'NR==5,NR==11{a=$2};NR==15,NR==21{b=$2} {printf "%d\n", $b-$a}' input.in > temp.in
但得到了错误
awk: (FILENAME=input.in FNR=20) fatal: attempt to access field -1052
任何想法如何用awk表达,如果那不起作用,那么为什么我不能用上面的awk乘法呢?谢谢!
答案 0 :(得分:1)
这可以一次性完成数学
$ awk -v c=1 '/^&/ {s++}
s==1 {a[$1]=$2}
s==3 {print $1,a[$1],$2,c*(a[$1]-$2)}
/@type/ {s++}' file
2.0 -1052.7396157664 -1052.5384564253 -0.201159
2.5 -1052.7330560932 -1052.7040374678 -0.0290186
3.0 -1052.7540013664 -1052.7542803612 0.000278995
3.5 -1052.7780321236 -1052.7781686744 0.000136551
4.0 -1052.7948229060 -1052.7948927247 6.98187e-05
4.5 -1052.8081313831 -1052.8081704241 3.9041e-05
5.0 -1052.8190310613 -1052.8190543049 2.32436e-05
您可以轻松删除装饰并添加打印格式。幻数1=g1
和3=2*g2-1
对应于数据组1和2,因为数据文件中显示的顺序也可以转换为awk
变量。
计数器s
会跟踪您是否在一组中,奇数对应于集合之间的集合和偶数。增量在开始模式和结束模式下完成。增量语句的顺序是这样设置的,它们不会在模式之后打印(首先取消设置,打印设置值,最后重置}。您可以更改顺序并观察效果。
答案 1 :(得分:0)
在第一次尝试中,您应该替换该行:
awk '{printf "%11.2f\n", "$C"*$1 }' tmp4.in > tmp5.in
与那一个:
awk -v C=$C '{printf "%11.2f\n", C*$1 }' tmp4.in > tmp5.in
您正在使用带有awk的符号混合bash shell的符号。
$
的变量,并将其与$
一起使用。$
来使用变量。然而,有一些特殊的变量:$ 1 $ 2 ...... $C
,但shell无法在单引号中看到它。这就是为什么你必须编写awk -v C=$C
以便将shell变量$C
转移到名为C
的awk变量。在你使用awk的其他尝试中,我们也可以看到这样的错误。现在我想你会成功。
答案 2 :(得分:0)
这可能就是你要找的东西:
$ cat tst.awk
/^[@&]/ { lineNr=0; next }
{
++lineNr
if (lineNr in prev) {
print $1, c * ($2 - prev[lineNr])
}
prev[lineNr] = $2
}
$ awk -v c=100000 -f tst.awk file
2.0 20115.9
2.5 2901.86
3.0 -27.8995
3.5 -13.6551
4.0 -6.98187
4.5 -3.9041
5.0 -2.32436