![リスト内に文字列が存在するかどうかを確認し、文字列が存在する場合は3番目のファイルを出力します。](https://rvso.com/image/97245/%E3%83%AA%E3%82%B9%E3%83%88%E5%86%85%E3%81%AB%E6%96%87%E5%AD%97%E5%88%97%E3%81%8C%E5%AD%98%E5%9C%A8%E3%81%99%E3%82%8B%E3%81%8B%E3%81%A9%E3%81%86%E3%81%8B%E3%82%92%E7%A2%BA%E8%AA%8D%E3%81%97%E3%80%81%E6%96%87%E5%AD%97%E5%88%97%E3%81%8C%E5%AD%98%E5%9C%A8%E3%81%99%E3%82%8B%E5%A0%B4%E5%90%88%E3%81%AF3%E7%95%AA%E7%9B%AE%E3%81%AE%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%82%92%E5%87%BA%E5%8A%9B%E3%81%97%E3%81%BE%E3%81%99%E3%80%82.png)
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.tab
、1
ハッシュ変数に存在する場合は に置き換え、そうでない場合は に置き換えます0
。\h\K
は空白の存在を正に調べるため、最初の列が一致しないようにします。- 次に変更した行を印刷します