リスト内に文字列が存在するかどうかを確認し、文字列が存在する場合は3番目のファイルを出力します。

リスト内に文字列が存在するかどうかを確認し、文字列が存在する場合は3番目のファイルを出力します。

2 つのファイル (「data.tab」と「mylist.tab」) があります。

私の「data.tab」ファイルは次のようになります:

Info_1    abc1     abc2     abc3
Info_2    abc5     ghi4
Info_3    abc10
Info_4    abc8     abc7     abc87    klm78    abc99
Info_5    

私の「mylist.tab」ファイルは次のようになります:

abc2
abc10
abc34
abc99
abc78
abc8
abc3
abc5
abc4

「data.tab」内の各文字列 (列 1 を除く) が「mylist.tab」に存在するかどうかを検索したいと思います。3 番目のファイル「output.tab」を作成し、文字列が存在する場合は、それぞれの行/列に「1」を、存在しない場合は「0」を含めたいと思います。

例: "output.tab"

Info_1   0    1     1
Info_2   1    0
Info_3   1
Info_4   1    0     0    0    1
Info_5   

「data.tab」には行ごとに異なる数の列が含まれていることに注意してください。

答え1

これは awk で簡単に表現できます。

awk 'FNR==NR { h[$1]; next } { for(i=2; i<=NF; i++) $i = ($i in h)? 1 : 0 } 1' mylist.tab data.tab

または、より読みやすい形式では:

パース.awk

# Collect mylist.tab into the `h` associative array
FNR==NR {
  h[$1]
  next
}

# For all but the first column in data.tab check and record if it is in `h`
{ 
  for(i=2; i<=NF; i++) 
    $i = ($i in h) ? 1 : 0 
}

# Short for { print $0 }
1

次のように実行します:

awk -f parse.awk mylist.tab data.tab

出力:

Info_1 0 1 1
Info_2 1 0
Info_3 1
Info_4 1 0 0 0 1
Info_5

またはタブ区切りの列の場合:

awk -v OFS='\t' -f parse.awk mylist.tab data.tab

出力:

Info_1  0   1   1
Info_2  1   0
Info_3  1
Info_4  1   0   0   0   1
Info_5

答え2

Perl が救世主です!

リスト要素をハッシュに保存し、テーブルを読み取り、空白で分割し、ハッシュをチェックして 0 または 1 を出力します。

#!/usr/bin/perl
use warnings;
use strict;

my %in_list;
open my $LIST, '<', 'mylist.tab' or die $!;
while (<$LIST>) {
    chomp;
    $in_list{$_} = 1;
}

open my $TAB, '<', 'data.tab';
while (<$TAB>) {
    my @cells = split;
    print shift @cells, "\t";
    print join "\t", map $in_list{$_} ? 1 : 0, @cells;
    print "\n";
}

答え3

mylist.tab からスクリプトsedを作成し、それを data.tab で実行するには、次のようにします。sed

sed \
    -e '1i s/^[ \\t]*//' \
    -e 's@\(.*\)@s/\\([ \\t]\\)\1\\b/\\11/@g' \
    -e '$as/\\([ \\t]\\)[^ \\t]\\{2,\\}\\b/\\10/g' mylist.tab \
    > /tmp/x.sed 
sed -f /tmp/x.sed data.tab

注意: 「mylist.tab」内のすべての文字列は少なくとも 2 文字であると想定しています。

答え4

別のperl解決策

$ perl -lne 'if(!$#ARGV){ $h{$_}=1 }
             else{ s/\h\K\H+/$h{$&} ? 1 : 0/ge; print }
            ' mylist.tab data.tab
Info_1    0     1     1
Info_2    1     0
Info_3    1
Info_4    1     0     0    0    1
Info_5    
  • if(!$#ARGV){ $h{$_}=1 }単語のハッシュを構築するmylist.tab
  • s/\h\K\H+/$h{$&} ? 1 : 0/geの行についてはdata.tab1ハッシュ変数に存在する場合は に置き換え、そうでない場合は に置き換えます0\h\Kは空白の存在を正に調べるため、最初の列が一致しないようにします。
  • 次に変更した行を印刷します

関連情報