从文件中提取特定的一组行

时间:2010-08-19 01:29:03

标签: python awk text-processing

我有许多大的(约30 MB一块)制表符分隔的文本文件,其中包含可变宽度的行。我想从第n个(这里,n = 4)和倒数第二行(最后一行为空)中提取第二个字段。我可以使用awk单独获取它们:

awk 'NR==4{print $2}' filename.dat

和(我完全不了解这一点,但是)

awk '{y=x "\n" $2};END{print y}' filename.dat

但是有没有办法让他们在一个电话中聚在一起?我的更广泛的意图是将它包装在Python脚本中,以便从单独的目录中的大量文件(数千个)中获取这些值,并且我希望减少系统调用的数量。非常感谢 -

编辑:我知道我可以用Python读取整个文件以提取这些值,但认为awk可能更适合该任务(与附近的两个值之一有关)大文件的结尾)。

4 个答案:

答案 0 :(得分:3)

awk 'NR==4{print $2};{y=x "\n" $2};END{print y}' filename.dat

答案 1 :(得分:2)

您可以将行数传递给awk:

awk -v lines=$( wc -l < filename.dat ) -v n=4 '
    NR == n || NR == lines-1 {print $2}
' filename.dat

注意,在wc命令中,使用<重定向来避免打印文件名。

答案 2 :(得分:1)

以下是如何在Python中实现它而不读取整个文件

要获得第n行,您别无选择,只能将文件读取到第n行,因为这些行是可变宽度。

要获得倒数第二行,猜测该行的长度(慷慨)并在文件结束前寻找那么多字节。

read()从您寻求的角度来看。计算换行符的数量 - 您至少需要两个。如果少于2个换行符加倍猜测并再试一次

拆分您在换行符中读取的数据 - 您寻找的行将是拆分中的倒数第二个项目

答案 3 :(得分:1)

这是我在Python中的解决方案。灵感来自this other code

def readfields(filename,nfromtop=3,nfrombottom=-2,fieldnum=1,blocksize=4096):
    f = open(filename,'r')
    out = ''
    for i,line in enumerate(f):
        if i==nfromtop:
            out += line.split('\t')[fieldnum]+'\t'
            break
    f.seek(-blocksize,2)
    out += str.split(f.read(blocksize),'\n')[nfrombottom].split('\t')[fieldnum]
    return out

当我对其进行分析时,差异比使用子进程模块调用awk(awk 'NR==4{print $2};{y=x $2};END{print y}' filename.dat)的解决方案快0.09秒。这不是一个交易破坏者,但当其余的脚本在Python中时,似乎有一个回报去(特别是因为我有很多这些文件)。