繁体   English   中英

在文件linux中每行下面加总行

[英]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_replacementcollections.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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM