Überprüfen Sie, ob die Zeichenfolge in einer Liste vorhanden ist, und geben Sie eine dritte Datei aus, wenn die Zeichenfolge vorhanden ist.

Überprüfen Sie, ob die Zeichenfolge in einer Liste vorhanden ist, und geben Sie eine dritte Datei aus, wenn die Zeichenfolge vorhanden ist.

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 sedSkript 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 perlLö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/gefür Zeilen in data.tab, ersetzen durch , 1wenn in Hash-Variable vorhanden, sonst 0. Das \h\Kist ein positiver Lookbehind für das Vorhandensein von Leerzeichen, wodurch die Übereinstimmung der ersten Spalte vermieden wird
  • Drucken Sie dann die geänderte Zeile

verwandte Informationen