【问题标题】:how to subset a file - select a numbers of rows or columns如何对文件进行子集化 - 选择多个行或列
【发布时间】:2011-09-23 09:47:01
【问题描述】:

我想就如何对大文件(数百万行或几行)进行子集化获得您的建议/帮助。

例如,

(1) 我有大文件(数百万行,制表符分隔)。我想要这个文件的一个子集,只有从 10000 到 100000 的行。

(2) 我有大文件(数百万列,制表符分隔)。我想要这个文件的一个子集,只有从 10000 到 100000 的列。

我知道有一些工具,如 head、tail、cut、split 和 awk 或 sed。我可以用它们来做简单的子集。但是,我不知道如何完成这项工作。

您能给点建议吗?提前致谢。

【问题讨论】:

    标签: linux unix sed awk cut


    【解决方案1】:

    过滤行很容易,例如使用 AWK:

    cat largefile | awk 'NR >= 10000  && NR <= 100000 { print }'
    

    使用 CUT 过滤列更容易:

    cat largefile | cut -d '\t' -f 10000-100000
    

    正如 Rahul Dravid 所提到的,cat 不是必须的,正如 Zsolt Botykai 所补充的,您可以使用以下方法提高性能:

    awk 'NR > 100000 { exit } NR >= 10000 && NR <= 100000' largefile
    cut -d '\t' -f 10000-100000 largefile 
    

    【讨论】:

    • +1 这是我能想到的最简单的答案。但是这里不需要猫。我们可以在没有猫的情况下做到这一点。awk 'NR &gt;= 10000 &amp;&amp; NR &lt;= 100000 { print }' largefilecut -d '\t' -f 10000-100000 largefile
    • 您可以将第一个缩短为:awk 'NR &gt;= 10000 &amp;&amp; NR &lt;= 100000' largefile,这样会少一个过程,如果范围评估为真,则 awk 的默认操作是打印。但这会浪费 100000 之后的行,所以最好写成:awk 'NR &gt; 100000 { exit } NR &gt;= 10000 &amp;&amp; NR &lt;= 100000' largefile,因为这样处理将在第 100001 行停止。
    • 非常感谢 Drakosha 和其他人。我从你们那里得到了很多。你的脚本可以大大提高我的文件操作能力。
    • 由于您在 >100000 退出,因此无需检查 NRawk 'NR>100000{exit}NR>=10000' largefile
    【解决方案2】:

    一些不同的解决方案:

    对于行范围: 在sed

    sed -n 10000,100000p somefile.txt
    

    对于awk 中的列范围:

    awk -v f=10000 -v t=100000 '{ for (i=f; i<=t;i++) printf("%s%s", $i,(i==t) ? "\n" : OFS) }' details.txt
    

    【讨论】:

    • 非常感谢,拉胡尔。你给我一个关于 sed 和 awk 的好方向。虽然我可以在简单的操作中使用它们,但我从你那里学到了很多。
    【解决方案3】:

    在 sed 解决方案中被打败了,所以我将发布 perl dito。 打印选定的行。

    $ seq 100 | perl -ne 'print if $. >= 10 && $. <= 20' 
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    

    要打印选择性列,请使用

    perl -lane 'print $F[1] .. $F[3] '
    

    -F-a 结合使用,以选择分割行的分隔符。

    为了测试,使用seqpaste 生成一些列

    $ seq 50 | paste - - - - -
    1   2   3   4   5
    6   7   8   9   10
    11  12  13  14  15
    16  17  18  19  20
    21  22  23  24  25
    26  27  28  29  30
    31  32  33  34  35
    36  37  38  39  40
    41  42  43  44  45
    46  47  48  49  50
    

    让我们打印除第一列和最后一列之外的所有内容

    $ seq 50 | paste - - - - - | perl -lane 'print join "   ", $F[1] .. $F[3]'
    2   3   4
    7   8   9
    12  13  14
    17  18  19
    22  23  24
    27  28  29
    32  33  34
    37  38  39
    42  43  44
    47  48  49
    

    在上面的join 语句中,有一个选项卡,你可以通过 ctrl-v 选项卡得到它。

    【讨论】:

      【解决方案4】:

      对于第一个问题,从一个大文件中选择一组行,从头到尾管道非常简单。您想要从第 10000 行开始的大文件中的 90000 行。tail 从第 10000 行开始抓取大文件的后端,然后 head 砍掉除前 90000 行之外的所有行。

      tail -n +10000 largefile | head -n 90000 -
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-10-25
        • 1970-01-01
        • 1970-01-01
        • 2015-11-27
        • 2011-07-28
        相关资源
        最近更新 更多