我有 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”中的每個字串(第一列除外)是否存在於“mylist.tab”中。我想創建第三個檔案“output.tab”,如果該字串存在,那麼我將在相應的行/列中包含“1”,否則包含“0”。
範例:“輸出.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.tabsed
建立腳本並在 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
積極的向後查找,從而避免第一列匹配- 然後列印修改後的行