提问人:Gery 提问时间:10/15/2023 最后编辑:Gery 更新时间:10/16/2023 访问量:152
在 bash 中比较两个大文件并寻找性能 [已关闭]
Comparing two large files in bash and looking for performance [closed]
问:
关于这个问题,我已经挠头了一段时间。我有两个文件:
base.csv
6517.49,450.0N,450.0N,-79.5664,-7.9726,280.434,-7.9726
6542.77,300.0N,300.0N,-79.5376,-8.0679,280.462,-8.0679
6530.41,300.0N,300.0N,-79.6216,-7.9845,280.378,-7.9845
tocompare.csv
7233.28,-81.59,-5.13513513514,278.41,-5.13513513514
7224.23,-81.59,-5.1951951952,278.41,-5.1951951952
并且两个文件的第一列值之间的百分比差异低于 10.5%(例如,第 1 行 -> in 与 in ),我需要输出两个文件的列。为了获得我使用的百分比差异(我使用以下值作为示例,因为它们只满足<两个值之间差异 10.5%)的条件:7233.28
tocompare.csv
6517.49
base.csv
awk
$ echo 6542.77 7224.23 | awk 'function abs(x){ return ((x < 0.0) ? -x : x) } { print (abs($1-$2)/$1)*100"%" }'
10.4155%
因此,在第一次比较运行中,我希望将 () 与 中第一列的所有值进行比较。因此,与第一列相比是 3 倍。然后,该过程再次开始,依此类推。7233.28
tocompare.csv
base.csv
7233.28
base.csv
7224.23
下面是第 1 次和第 2 次运行的结果,其中第 1 次运行不打印任何内容,并且在第 2 次运行后只出现一个结果(即。 与 ):6542.77
7224.23
2nd column base.csv 2nd column tocompare.csv 3rd column tocompare.csv
300.0N -81.59 -5.1951951952
我怀疑的是性能,因为原始文件非常大。例如,基于这两个 CSV 文件,将有 6 行比较(有 3 行,有 2 行)。原始文件分别有 300 行和 20 000 行(因此,有 600 万次比较)。但是,由于条件不满足,我希望不会打印任何内容,这支持计算的时间和性能。base.csv
tocompare.csv
那么,nice是完成这项任务的正确工具吗?如果是这样,我该如何比较这两个文件以获得预期的输出文件?awk
任何提示将不胜感激,
答:
鉴于:
head *.csv
==> base.csv <==
6517.49,450.0N,450.0N,-79.5664,-7.9726,280.434,-7.9726
6542.77,300.0N,300.0N,-79.5376,-8.0679,280.462,-8.0679
6530.41,300.0N,300.0N,-79.6216,-7.9845,280.378,-7.9845
==> tocompare.csv <==
7233.28,-81.59,-5.13513513514,278.41,-5.13513513514
7224.23,-81.59,-5.1951951952,278.41,-5.1951951952
我能为你得出的最接近下一步的是这个 Ruby:
ruby -r csv -e 'BEGIN{opts={:converters => :numeric} }
base,tc=[0,1].map{|fn| CSV.parse(File.open(ARGV[fn]).read, **opts)}
idx={}
tc.each.with_index{|tc_row, i|
base.each.with_index{|base_row,j| idx[i]=j if (base_row[0]-tc_row[0]).abs/base_row[0]<0.105}
}
idx.each{|k,v| puts "#{base[k][1]}\t#{tc[v][1]}\t#{tc[v][2]}" }
' base.csv tocompare.csv
指纹:
300.0N -81.59 -5.1951951952
假设/理解:
- 我们想找到两个文件的笛卡尔乘积的“百分比差”(即,所有第一列来自 + 所有第一列来自
base.csv
tocompare.csv
) - 仅当“百分比差异”< 10.5 时生成 3 列输出
一个想法:awk
$ cat abs.awk
function abs(x) { return ((x < 0.0) ? -x : x) }
BEGIN { FS = "," }
FNR==NR { col1[++cnt] = $1 # 1st file: save column 1
col2[ cnt] = $2 # save column 2
next
}
{ for (i=1; i<=cnt; i++) # 2nd file: loop through list of 1st columns from 1st file
if (abs(col1[i]-$1)/col1[i] * 100 < 10.5) # if calculation is less than 10.5 then ...
print col2[i], $2, $3 # print 3-column output
}
这将产生:
$ awk -f abs.awk base.csv tocompare.csv
300.0N -81.59 -5.1951951952
看看性能...
OP 提到实际文件是 300 行 () 和 20,000 行 ()。我复制了两个文件中的行,以达到所需的行数:base.csv
tocompare.csv
$ wc -l base.300.csv tocompare.20K.csv
300 base.300.csv
20000 tocompare.20K.csv
针对较大文件对脚本进行计时:awk
$ time awk -f abs.awk base.300.csv tocompare.20K.csv > x
real 0m1.127s
user 0m1.094s
sys 0m0.032s
笔记:
i7-1260P
running 和Ubuntu 22.04
GNU awk 5.1.0
- ~1.2 秒执行 600 万次操作
abs() / comparison
- 在之前对问题的编辑中,OP 提到了“摆脱值”和“跳过计算”,但我们没有得到关于这意味着什么的细节;如果 OP 有额外的逻辑可以让我们减少操作次数,那么就有可能将运行时间减少到当前 ~1.2 秒以下
abs() / comparison
验证我们得到相同的结果:
$ sort -u x
300.0N -81.59 -5.1951951952
评论
awk
评论
diff
comm
join