【问题标题】:Printing only nth columns from csv file [closed]仅从 csv 文件打印第 n 列 [关闭]
【发布时间】:2015-01-23 10:57:24
【问题描述】:

我有一个巨大的(大约 170 万列,每列 2 行).csv 文件,有点像这样:

Position 1 2 3 4 ... 1.6M
Coverage 1 1 1 2 ... 1

我需要先提取第 1 列,然后提取第 1000 列、第 2000 列等等,直到文件末尾。我是编程之类的新手。这对 perl 或 awk 是否可行,如何实现?我可以访问 Windows 和 Linux 系统。 提前致谢!

迈克尔

【问题讨论】:

  • 所以它总是第 1 次,然后第 1000K 次?
  • awk 的字段长度有限,只有 100 个字段。尝试使用 gawk
  • @fedorqui 是的。
  • @morsik 我已经安装了 gawk,感谢您的建议。
  • 试试这个 gawk '{ for (i=1;i test (stackoverflow.com/questions/15716965/print-columns-with-awk)

标签: perl csv awk multiple-columns


【解决方案1】:

试试这条线:

awk -v n=1000 '{printf "%s%s", $1, FS;
                for(i=n;i<=NF;i+=n)printf "%s%s", $i, (i+n>NF?RS:FS)}' file

【讨论】:

    【解决方案2】:

    这可以在 Perl 中简化为单行代码:

    perl -lane ' for (@F) { print if !($a++ % 1000) } ' yourfile.csv
    

    这使用模运算符% 来检查列号是否为1000(或0)的倍数,如果是,则打印该值。 -a 开关在空白处分割行。如果要指定分隔符,例如\t 你可以用 -F"\t" 做到这一点。

    如果将整行加载到内存中会降低程序的速度,您可以使用输入记录分隔符进行调整。在本例中,我将其设置为空格:

    perl -l -0040 -ane '!(($.-1) % 1000) and print ' yourfile.csv
    

    这会将空格作为输入记录分隔符,一次读取一列。 -l 选项将 chomp "行" 并删除空格,并为打印提供换行符。 $. 是当前行号。

    【讨论】:

      【解决方案3】:

      下面的awk 程序应该做。这里我对一个有 10000 条记录的文件执行,同样可以对任意数量的记录执行。

      $ awk '{for(i=0;i<=NF; i+=1000){printf("%s ", $(i==0?1:i))} print "" }' file
      

      输出:

      1 1000 2000 3000 4000 5000 6000 7000 8000 9000 10000 
      1 1000 2000 3000 4000 5000 6000 7000 8000 9000 10000 
      1 1000 2000 3000 4000 5000 6000 7000 8000 9000 10000 
      1 1000 2000 3000 4000 5000 6000 7000 8000 9000 10000 
      1 1000 2000 3000 4000 5000 6000 7000 8000 9000 10000 
      1 1000 2000 3000 4000 5000 6000 7000 8000 9000 10000 
      1 1000 2000 3000 4000 5000 6000 7000 8000 9000 10000 
      1 1000 2000 3000 4000 5000 6000 7000 8000 9000 10000 
      1 1000 2000 3000 4000 5000 6000 7000 8000 9000 10000 
      

      【讨论】:

      • 对不起,这不只是为每一行打印一堆数字吗?相同的数字,无论输入中的内容是什么?
      • @TLP,感谢您指出。我已经更新了程序。
      【解决方案4】:

      试试这个几乎可读的 perl:

      $ cat foo.pl
      use strict;
      use warnings;
      
      my $every = 1000;
      while (my $line = <STDIN>) {
          chomp $line;
          my @columns = split(' ', $line);
          print "$columns[0]";
          my $i = $every;
          while ($i < @columns) {
              print " $columns[$i]";
              $i += $every;
          }
          print "\n";
      }
      
      $ perl foo.pl < input.csv
      

      【讨论】:

        【解决方案5】:

        我会试试的:

        cat > ex.txt
        1 2 3 4 5 6 7 8 9 10 11 12 13
        1 1 1 1 1 1 1 2 1 2  1  1  3
        

        当在线时:

        perl -e 'open FH, "ex.txt"; $line1=<FH>; $line2=<FH>; @tab1=split(/\s+/, $line1); @tab2=split(/\s+/, $line2); for ($i=0; $i<14; $i+=4) { print $tab1[$i]."/".$tab2[$i]."\n"; } close FH;'
        

        结果:

        1/1
        5/1
        9/1
        13/3
        

        不在一行中:

        # open file
        open FH, "ex.txt";
        # extract the two lines
        $line1=<FH>;
        $line2=<FH>;
        # extract the elements for each 
        @tab1=split(/\s+/, $line1);
        @tab2=split(/\s+/, $line2);
        # and print, here step 4
        for ($i=0; $i<14; $i+=4) { 
          print $tab1[$i]."/".$tab2[$i]."\n";
        }
        close FH;
        

        如果您有 160 万个项目,会消耗大量内存!

        【讨论】:

        • 为什么不跳过使用自己的句柄而直接使用&lt;&gt;?这是单行代码,因此您可以编写缩写代码。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-07-08
        • 2017-04-24
        • 2017-04-23
        • 1970-01-01
        • 2022-01-06
        • 2020-02-22
        相关资源
        最近更新 更多