【问题标题】:Organising Data组织数据
【发布时间】:2013-12-14 06:54:00
【问题描述】:

我的数据文件如下所示:

chr1 762440 762981 SAMD11 
chr1 858932 859148 KLHL17 SAMD11 NOC2L 
chr1 859786 860145 KLHL17 SAMD11 NOC2L
chr1 890663 891747 KLHL17 NOC2L  SAMD11  HES4 

我想要的是将所有名称排列在前三列中的值的下方。

类似的东西

chr1 762440 762981 SAMD11 
chr1 858932 859148 KLHL17
chr1 858932 859148 SAMD11 
chr1 858932 859148 NOC2L 
chr1 859786 860145 KLHL17 
chr1 859786 860145 SAMD11 
chr1 859786 860145 NOC2L

这个输出是前三行的,但整个集合都需要。

每行名字的数量不固定,请记住这一点(可以是1个或5个或10个或20个名字)

What I thought

使用 sed -i .bak 将名称与前三列中的值一起放在另一个下方。

但最后变得过于复杂了。

您能想出一个更简单的方法来解决这个问题吗?

谢谢

【问题讨论】:

  • 你说你想要前 3 列作为你的输出,但是你想要的输出显示 4 列...
  • 嗯,我的意思是,“我想将名称与前三列中的值一起排列在 pother 的下方”。这就是为什么 4 列输出。

标签: python perl bash sed


【解决方案1】:
#!/usr/bin/perl
use warnings;
use strict; 

读入你的文件:

my $infile = 'in.txt';
open my $input, '<', $infile or die "Can't open to $infile: $!";

在空格上分割每一行(尽管如果您的数据是制表符分隔的,我会推荐split(/\t/)

while (<$input>){
    my @split = split(/\s+/);
    print "$split[0]\t$split[1]\t$split[2]\t$split[3]\n";
}

输出:

chr1    762440  762981  SAMD11
chr1    858932  859148  KLHL17
chr1    859786  860145  KLHL17
chr1    890663  891747  KLHL17
chr1    896072  896354  NOC2L
chr1    954920  955343  HES4
chr1    1195296 1195488 PUSL1
chr1    1243975 1244505 UBE2J2
chr1    1284370 1284709 ACAP3
chr1    1373711 1374872 CCNL2

【讨论】:

  • 我不明白它是如何为 OP 工作的,但它没有从第五个字段打印到最后。
  • 是的,我同意,我用一小组数据重新测试了它。它仅适用于部分:(CHR1 762440 762981 SAMD11 CHR1 859148 KLHL17 SAMD11 NOC2L CHR1 859786 860145 KLHL17 SAMD11 NOC2L CHR1 890663 891747 KLHL17 NOC2L SAMD11 HES4 CHR1 896072 896354 NOC2L KLHL17 SAMD11 HES4 SPAN>
  • @FlyingFrog 可以选择答案,但请求者应该等待一段时间。它可能会显示出更好的答案。
  • 这取决于每列的分隔方式,以及每列中的数据是否包含空格。
  • Chr1 762440 762981 SAMD11 CHR1 858932 85932 85932 85932 859148 KLHL17 SAMD11 NOC2L CHR1 859786 860145 KLHL17 SAMD11 NOC2L CHR1 890663 891747 KLHL17 NOC2L SAMD11 HES4 CHR1 896072 896354 NOC2L KLHL17 SAMD11 HES4 SPAN>
【解决方案2】:

使用awk

awk '{for (i=4;i<=NF;i++) print $1,$2,$3,$i}' file
chr1 762440 762981 SAMD11
chr1 858932 859148 KLHL17
chr1 858932 859148 SAMD11
chr1 858932 859148 NOC2L
chr1 859786 860145 KLHL17
chr1 859786 860145 SAMD11
chr1 859786 860145 NOC2L
chr1 890663 891747 KLHL17
chr1 890663 891747 NOC2L
chr1 890663 891747 SAMD11
chr1 890663 891747 HES4

【讨论】:

    【解决方案3】:

    在 bash 中(100% 内部命令) 我有这个答案:

    #!/bin/bash
    
    
    while read ONE TWO THREE FOUR
    do
        for ARG in $FOUR
        do
            if [ ${ARG:0:1} != "(" ]    #<-- filtering out args with parentheses
            then
                echo "$ONE $TWO $THREE $ARG"
            fi
        done
    done <"/path/to/your/datafile"
    

    但由于您更改了问题,这也会将答案更改为:

    #!/bin/bash
    
    
    while read ONE TWO THREE FOUR
    do
        for ARG in $FOUR
        do
            echo "$ONE $TWO $THREE $ARG"
        done
    done <"/path/to/your/datafile"
    

    【讨论】:

      【解决方案4】:

      怎么样:

      while(<DATA>) {
          chomp;
          my @data = split" ",$_;
          my $prefix = join" ",@data[0..2];
          for(3 .. $#data) {
              next if $data[$_] =~ /\([-+]?\d+\)/;
              say $prefix, " ", $data[$_];
          }
      }
      
      __DATA__
      chr1 762440 762981 SAMD11 (-98410)
      chr1 858932 859148 KLHL17 (-36927), SAMD11 (-2081), NOC2L (+35639)
      chr1 859786 860145 KLHL17 (-36001), SAMD11 (-1155), NOC2L (+34713)
      

      输出:

      chr1 762440 762981 SAMD11
      chr1 858932 859148 KLHL17
      chr1 858932 859148 SAMD11
      chr1 858932 859148 NOC2L
      chr1 859786 860145 KLHL17
      chr1 859786 860145 SAMD11
      chr1 859786 860145 NOC2L
      

      【讨论】:

        【解决方案5】:

        由于您也有 Python 标记,因此我将在 Python 中执行此操作(从标准输入或命令行上的文件读取输入,并将输出写入标准输出)。

        #!/usr/bin/python
        
        import fileinput
        
        for line in fileinput.input():
            parts = line.strip().split()
            first_three = " ".join(parts[:3])
        
            for code in parts[3:]:
                print("{first_three} {code}".format(first_three=first_three, code=code))
        

        【讨论】:

          【解决方案6】:

          这是我在 Perl 中的做法:

          #!/usr/bin/perl
          
          use strict;
          use warnings;
          use 5.010;
          
          while (<DATA>) {
            chomp;
            my @line = split;
            for my $field (@line[3 .. $#line]) {
              say "@line[0 .. 2] $field";
            }
          }
          
          __END__
          chr1 762440 762981 SAMD11 
          chr1 858932 859148 KLHL17 SAMD11 NOC2L 
          chr1 859786 860145 KLHL17 SAMD11 NOC2L
          chr1 890663 891747 KLHL17 NOC2L  SAMD11  HES4 
          

          【讨论】:

            【解决方案7】:
            sed 's/^/\
            /
            t b
            : b
            s/\(\n\)\(\([^[:blank:][:cntrl:]]\{1,\}[[:blank:]]\{1,\}\)\{3\}\)\([^[:blank:][:cntrl:]]\{1,\}\)[[:blank:]]\{1,\}\([^[:blank:][:cntrl:]][^[:cntrl:]]*\)[[:blank:]]*$/\1\2\4\1\2\5/
            t b
            s/^\n//' YourFile
            

            处理每一行,扩展任何最后一个参数。首先t b 可以被删除,但它会通过安全重置测试

            【讨论】:

              【解决方案8】:

              这可能对你有用(GNU sed):

              sed -r 's/^((\S+\s+){3})(\S+)\s+(\S+)/\1\3\n\1\4/;P;D' file
              

              【讨论】:

                猜你喜欢
                • 2017-01-17
                • 1970-01-01
                • 1970-01-01
                • 2018-03-16
                • 2012-07-17
                • 2012-02-27
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多