[英]Sum lines below each line in a file linux
我有这样的输入
A 100
B 150
C 200
D 250
E 300
我想要的输出是以上所有元素的总和:像这样
A to A - 100
A to B - 250
A to C - 450
A to D - 700
A to E - 1000
B to B - 150
B to C - 350
B to D - 600
B to E - 900
C to C - 200
C to D - 450
C to E - 650
D to D - 250
D to E - 550
E to E - 300
文件大小约为250 MB。 我编写了一个python程序,该程序首先将每行存储在字典中。 但是我认为这对于大量投入是不可行的。 我是使用Linux的初学者。
只需存储值和嵌套循环即可:
awk '
{ label[NR]=$1; val[NR]=$2 }
END {
for (i=1; i<=NR; i++) {
sum = 0
for (j=i; j<=NR; j++) {
sum += val[j]
print label[i] " to " label[j] " - " sum
}
}
}
' file
我认为这对于大型文件仍然很慢(您必须将整个文件存储在内存中,并且它是O(N ^ 2)(或者是O(NlogN),已经有一段时间了...)操作我怀疑将数据放入数据库会帮助您。
您说,您的输入文件约为250MB。 我们称它为250MB或262144000字节。 您的代表输入是每行7个字节-一个字符,两个空格,一个三位数和一个换行符。 这意味着某些行的数量为37449142。
如果您打算最终为输入文件中的每对可能的行生成一个输出,看起来似乎是这样,那么您需要准备好存储37449142 * 37449143/2 = 701219136992653独立的输出行。 在每个代表字节为7个字节的情况下,忽略了大多数字节可能会变得更大的事实,那就是4908533958948571字节,即您需要存储的4464 TB数据。
希望您的预算为一些大型EMC阵列提供足够的资金。 否则,就像您怀疑的那样,这可能在不可行的方面会有点...
使用python:
>>> value =[]
>>> name = []
>>> f=open('yourfile.txt')
>>> for x in f:
... x=x.strip()
... na,va = x.split()
... name.append(na)
... value.append(va)
...
>>> name
['A', 'B', 'C', 'D', 'E']
>>> value
['100', '150', '200', '250', '300']
>>> for i in range(len(name)):
... for j in range(i,len(name)):
... print name[i],name[j],str(sum(map(int,value[i:j+1])))
...
输出:
A A 100
A B 250
A C 450
A D 700
A E 1000
B B 150
B C 350
B D 600
B E 900
C C 200
C D 450
C E 750
D D 250
D E 550
E E 300
在Python中,您可以使用itertools.combinations_with_replacement
和collections.OrderedDict
进行此操作。 内存中唯一存储的是一个字典,其中第一列的项目作为键,第二列的项目作为值:
from itertools import combinations_with_replacement
from collections import OrderedDict
with open('file.txt') as f:
data = OrderedDict((k, int(v)) for k, v in (line.split() for line in f))
start = None
tot = 0
for k1, k2 in combinations_with_replacement(data.iterkeys(), 2):
if k1 != start:
start = k1
tot = data[k1]
print '{} to {} - {}'.format(k1, k2, tot)
else:
tot += data[k2]
print '{} to {} - {}'.format(k1, k2, tot)
输出:
A to A - 100
A to B - 250
A to C - 450
A to D - 700
A to E - 1000
B to B - 150
B to C - 350
B to D - 600
B to E - 900
C to C - 200
C to D - 450
C to E - 750
D to D - 250
D to E - 550
E to E - 300
这是一个快速的:
awk '{s+=$2; printf("%s - %d\n", $1, s)}' <your-file>
如果要打印A to A, A to B
等,我们将不得不更多:
(在tcsh中)
foreach n (`seq 5 -1 1`)
tail -$n <your-file> | awk '{s+=$2; if (a) NR; else{ a=$1;} printf("%s to %s - %d\n", a, $1, s);}'
end
样本输出:
A - 100
B - 250
C - 450
D - 700
E - 1000
B to B - 150
B to C - 350
B to D - 600
B to E - 900
C to C - 200
C to D - 450
C to E - 750
D to D - 250
D to E - 550
E to E - 300
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.