使用perl将文件中的模式替换为该特定列的标题

时间:2014-03-06 13:07:42

标签: perl bash

我正在使用以下文件格式:

POS1    POS2    ID1 ID2 ID3 ID4 …
1   ### 0/0:.:58:.:.    0/0:.:51:.:.    0/0:.:104:.:.   0/0:.:16:.:.    
2   ### 0/0:89:.:.:.    0/0:75:.:.:.    0/0:125:.:.:.   0/0:57:.:.:.    
3   ### 0/0:.:93:.:.    0/0:.:85:.:.    0/0:.:127:.:.   0/0:.:60:.:.    
4   ### .:.:.:.:.   0/0:7:.:.:. .:.:.:.:.   .:.:.:.:.   
5   ### .:.:.:.:.   .:.:.:.:.   .:.:.:.:.   .:.:.:.:.   
6   ### .:.:.:.:.   0/0:8:.:.:. .:.:.:.:.   .:.:.:.:.   
7   ### 0/0:24:.:.:.    0/0:41:.:.:.    0/0:17:.:.:.    0/0:33:.:.:.    
8   ### 0/0:39:.:.:.    0/0:59:.:.:.    0/1:68:.:.:.    0/0:77:.:.:.    
9   ### 0/0:.:18:.:.    0/0:.:36:.:.    0/0:.:26:.:.    0/0:.:38:.:.    
10  ### 0/0:.:18:.:.    0/0:.:32:.:.    0/0:.:24:.:.    0/0:.:34:.:.    
11  ### 0/1:18:.:.:.    0/0:28:.:.:.    0/0:24:.:.:.    0/0:34:.:.:.    
12  ### 0/0:.:13:.:.    0/0:.:22:.:.    0/0:.:23:.:.    0/0:.:35:.:.    
13  ### 0/0:.:25:.:.    0/0:.:30:.:.    0/0:.:34:.:.    0/0:.:38:.:.    
14  ### 0/0:20:.:.:.    0/0:28:.:.:.    0/0:34:.:.:.    0/0:39:.:.:.    
15  ### 0/0:19:.:.:.    0/0:27:.:.:.    0/0:32:.:.:.    0/0:39:.:.:.    
16  ### .:.:.:.:.   0/0:26:.:.:.    0/1:34:.:.:.    0/0:32:.:.:.    
17  ### .:.:.:.:.   .:.:.:.:.   0/0:.:9:.:. 0/0:.:13:.:.

我遇到的问题是尝试列出包含“0/1”模式的每个位置的ID。即使你们只能弄清楚如何用特定的列ID替换“0/1”,我也可以自己完成剩下的工作。列和行的数量变化很大,可能有数千个。

不同的表述:如果某个职位在该行中包含一个带有“0/1”的ID,则应列出其在

中找到“0/1”的列的列ID

是否可以使用perl(或bash)解决此问题以及如何解决?我仍然是这种语言的新手,只知道它只有4周。

我向前谢谢。

EDIT 示例输出应该是这样的:

POS1 POS2   
8   ### ID3
11  ### ID1
16  ### ID3

如果多个列包含0/1,那么该位置应该是所有ID。 对不起,如果我听起来有点混乱,在办公室度过漫长的一天。

2 个答案:

答案 0 :(得分:0)

我想你想要这样的东西?程序期望输入文件作为命令行上的参数。

use strict;
use warnings;

my @headers;

while (<>) {
  chomp;
  my @fields = split /\t/;
  if (@headers) {
    my @ids;
    for my $i (2 .. $#fields) {
      push @ids, $headers[$i] if $fields[$i] =~ m:0/1:;
    }
    print join("\t", $fields[0], @ids), "\n" if @ids;
  }
  else {
    @headers = @fields;
    print join("\t", @headers[0,1]), "\n";
  }
}

<强>输出

POS1  POS2
8 ID3
11  ID1
16  ID3

答案 1 :(得分:0)

awk '
    NR==1 {for (i=3; i<=NF; i++) head[i]=$i; print $1, $2; next}
    {
        line = $1 OFS $2
        found = 0
        for (i=3; i<=NF; i++) {
            if ($i ~ /0\/1/) {
                found = 1
                line = line OFS head[i]
            }
        }
        if (found) print line
    }
' file

或bash

file="filename.txt"
headers=( $(head -1 "$file") )
sed '1d' "$file" | while read -a fields; do      
    out=( ${fields[0]} ${fields[1]} )
    found=false
    for (( i=2; i<${#fields[@]}; i++ )); do          
        if [[ ${fields[i]} == *0/1* ]]; then              
            out+=(${headers[i]})
            found=true
        fi
    done
    $found && echo "${out[*]}"
done > output.txt