У меня есть 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". Я хотел бы создать третий файл "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
Используйте sed
для создания sed
скрипта из mylist.tab и запуска его на data.tab:
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
Положительный просмотр назад на наличие пробела, таким образом избегая сопоставления первого столбца- Затем распечатайте измененную строку