【问题标题】:extract specific set of lines from files从文件中提取特定的行集
【发布时间】:2011-03-31 21:22:35
【问题描述】:

我有很多大的(约 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 可能更适合该任务(与位于附近的两个值之一有关大文件的结尾)。

【问题讨论】:

    标签: python awk text-processing


    【解决方案1】:
    awk 'NR==4{print $2};{y=x "\n" $2};END{print y}' filename.dat
    

    【讨论】:

    • 我想我也不需要那个“\n”。
    【解决方案2】:

    你可以将行数传递给awk:

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

    注意,在wc 命令中,使用&lt; 重定向以避免打印文件名。

    【讨论】:

    • 谢谢 - 这个语法更合适。
    【解决方案3】:

    以下是如何在 Python 中实现此功能而不需要读取整个文件

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

    要获取倒数第二行,该行可能有多长(大方)并在文件结尾之前查找那么多字节。

    read() 从您所寻求的点开始。计算换行符的数量 - 你至少需要两个。如果少于 2 个换行符,请加倍猜测,然后重试

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

    【讨论】:

    • 谢谢!我在 [这里][code.activestate.com/recipes/120686-read-a-text-file-backwards/….在这种情况下,假定的字节数是 4096。想过做类似的事情......但我的 awk 行现在正在一堆文件上运行。 :)
    • @Stephen,对,但每次运行 awk 时,您仍然要启动一个 shell
    • 谢谢 - 我刚刚分析了一个纯 Python 解决方案,它在单个 awk 调用中胜出。我已经切换到它了。
    【解决方案4】:

    这是我在 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
    

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

    【讨论】:

    • 感谢 gnibbler 的建议。
    • 您应该只分析从 shell 调用 awk,而不是子进程模块。你可以用 shell 脚本做任何事情。但如果你打算做纯 Python,那就这样吧。
    • 我想我已经准备好在 Python 中使用 os.path.walk(),尽管我确信在这种情况下 find + awk 解决方案可能也足够了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-11-21
    • 1970-01-01
    • 2013-05-09
    • 1970-01-01
    • 2022-11-15
    • 1970-01-01
    相关资源
    最近更新 更多