![Überprüfen Sie, ob die Zeichenfolge in einer Liste vorhanden ist, und geben Sie eine dritte Datei aus, wenn die Zeichenfolge vorhanden ist.](https://rvso.com/image/97245/%C3%9Cberpr%C3%BCfen%20Sie%2C%20ob%20die%20Zeichenfolge%20in%20einer%20Liste%20vorhanden%20ist%2C%20und%20geben%20Sie%20eine%20dritte%20Datei%20aus%2C%20wenn%20die%20Zeichenfolge%20vorhanden%20ist..png)
Ich habe 2 Dateien („data.tab“ und „mylist.tab“).
meine "data.tab"-Datei sieht so aus:
Info_1 abc1 abc2 abc3
Info_2 abc5 ghi4
Info_3 abc10
Info_4 abc8 abc7 abc87 klm78 abc99
Info_5
meine Datei „mylist.tab“ sieht folgendermaßen aus:
abc2
abc10
abc34
abc99
abc78
abc8
abc3
abc5
abc4
Ich möchte suchen, ob jede Zeichenfolge in „data.tab“ (außer Spalte 1) in „mylist.tab“ vorhanden ist. Ich möchte eine dritte Datei „output.tab“ erstellen, in der ich, wenn die Zeichenfolge vorhanden ist, eine „1“ und andernfalls eine „0“ in die entsprechende Zeile/Spalte einfüge.
Beispiel: „output.tab“
Info_1 0 1 1
Info_2 1 0
Info_3 1
Info_4 1 0 0 0 1
Info_5
Bitte beachten Sie, dass „data.tab“ für jede Zeile eine unterschiedliche Anzahl von Spalten enthält.
Antwort1
Dies lässt sich unkompliziert in awk ausdrücken:
awk 'FNR==NR { h[$1]; next } { for(i=2; i<=NF; i++) $i = ($i in h)? 1 : 0 } 1' mylist.tab data.tab
Oder in einem besser lesbaren Format:
parse.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
Führen Sie es wie folgt aus:
awk -f parse.awk mylist.tab data.tab
Ausgabe:
Info_1 0 1 1
Info_2 1 0
Info_3 1
Info_4 1 0 0 0 1
Info_5
Oder für tabulatorgetrennte Spalten:
awk -v OFS='\t' -f parse.awk mylist.tab data.tab
Ausgabe:
Info_1 0 1 1
Info_2 1 0
Info_3 1
Info_4 1 0 0 0 1
Info_5
Antwort2
Perl zur Rettung!
Speichern Sie die Listenelemente in einem Hash, lesen Sie dann die Tabelle, teilen Sie sie bei Leerzeichen auf und überprüfen Sie den Hash, um entweder 0 oder 1 auszugeben.
#!/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";
}
Antwort3
Verwenden Sie es sed
, um ein sed
Skript aus mylist.tab zu erstellen und es auf data.tab auszuführen:
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
Beachten Sie, dass ich davon ausgehe, dass alle Zeichenfolgen in „mylist.tab“ mindestens 2 Zeichen haben.
Antwort4
Eine andere perl
Lösung
$ 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 }
Erstellen Sie einen Hash von Wörtern inmylist.tab
s/\h\K\H+/$h{$&} ? 1 : 0/ge
für Zeilen indata.tab
, ersetzen durch ,1
wenn in Hash-Variable vorhanden, sonst0
. Das\h\K
ist ein positiver Lookbehind für das Vorhandensein von Leerzeichen, wodurch die Übereinstimmung der ersten Spalte vermieden wird- Drucken Sie dann die geänderte Zeile