2017-03-07 4 views
2

Ich habe file1:bash, um Informationen aus zwei Dateien

NM_000014 A2M 
NM_000015 NAT2 
NM_000016 ACADM 
NM_000017 ACADS 
NM_000018 ACADVL 
NM_000019 ACAT1 
NM_000020 ACVRL1 
NM_000021 PSEN1 
NM_000022 ADA 

Und file2:

NM_000019 
NM_000020 
NM_000020 
NM_12345 

Ich brauche Informationen von meinem file1 zu bekommen und es setzen Datei2 - so file3 erstellen:

NM_000019 ACAT1 
NM_000020 ACVRL1 
NM_000020 ACVRL1 
NM_12345 NO 

Hinweis - Ich kann eine ursprüngliche Sortierreihenfolge nicht ändern (also nicht comm und diff verwenden). Ich habe doppelte Zeile in file2 - das muss ich behalten (wc -l file2 == wc -l file3). Wenn es keine Übereinstimmung gibt - drucken NO

Ich habe etwa 70K Reihen und ich brauche keine schnellste Lösung. Mein Code ist in der Lage, die gleichen Ergebnisse zu vergleichen und zu drucken.

Code:

#!/bin/bash 

while read -r c; do 


grep $c file1 | uniq 

done <file2> file3 

Antwort

3

Mit awk:

$ awk 'NR==FNR{a[$1]=$2;next} {print ($1 in a?$1 OFS a[$1]:$1 OFS "NO")}' file1 file2 
NM_000019 ACAT1 
NM_000020 ACVRL1 
NM_000020 ACVRL1 
NM_12345 NO 

Erklärt:

NR==FNR{          # process the first file 
    a[$1]=$2         # hash records to a, $1 as key 
    next          # skip to next record 
} 
{            # process the second file 
    print ($1 in a?$1 OFS a[$1]:$1 OFS "NO") # print hashed value if found or NO 

# if($1 in a)        # another way of saying above 
#  print $1, a[$1] 
# else 
#  print $1, "NO" 
} 
+1

Der Vollständigkeit halber könnten Sie 'awk -v OFS =" \ t "'#my awk code ....' file1 file2' hinzufügen, um Felder durch Tabulatoren getrennt zu machen – Aserre

+0

@Aserre Danke, habe die Registerkarten nicht erwähnt, also habe ich das übersprungen . –

+0

@JamesBrown Vielen Dank für die perfekte awk Lösung .. sehr interessiert ist, dass in Ihrer Lösung Bedingung gilt wc -l file2 == wc -l file3 !! – Geroge

1

Also im Grunde Sie eine Datei mit Mustern haben, und eine zweite, die Sie diese Muster verwenden suchen möchten:

#!/bin/bash 

for PATTERN in $(cat $2); do 
    TMP=$(egrep $PATTERN $1) 
    if [ ! -z "$TMP" ]; then 
     echo "$TMP" 
    else 
     echo "$PATTERN NO" 
    fi 
done 

und einen schnellen Test:

$ bash filter.sh file1 file2 
NM_000019 ACAT1 
NM_000020 ACVRL1 
NM_000020 ACVRL1 
NM_12345 NO 
+0

Dies ist sehr nett zu Ihnen bash und Eingabedateien direkt vom Terminal. Könnten Sie mir bitte erklären, was ist der Teil für das Lesen von Dateien direktes Formular-Terminal? Das: $ (Katze $ 2) ?? – Geroge

+0

Nun, es ist wirklich einfach, der n-te Kommandozeilenparameter kann mit $ n referenziert werden ...das ist es :-) Also die Annahme ist, dass die Datei mit den Daten übergeben wird. Siehe Beispiel: http://wiki.bash-hackers.org/scripting/posparams oder direkt im bash-Handbuch: https://www.gnu.org/software/bash/manual/bashref.html#Positional-Parameters – andipla

1

Versuchen Sie mit diesem if Satz zu Ihrem Code hinzugefügt:

if ! grep -q $i fileone ; then 
    echo -e $i " NO" 
fi 

Zum Beispiel:

#!/bin/bash 
while read -r c; do grep $c fileone | uniq; done < filetwo 
for i in $(cat filetwo) 
do 
    if ! grep -q $i fileone ; then 
    echo -e $i " NO" 
    fi 
done 

Es wird nicht bei keinem Spiel von einer Reihe von Datei2 in Datei1 drucken.

0

Try Einfügen-Befehl. Dies ist weniger edle Form als awk. Ich bevorzuge Awk, aber Paste Befehl sollte Ihnen helfen.

Paste Datei1 Datei2 file3 ... etc ..fileN

Sie Befehlsausgabe wie gewohnt in eine Datei umleiten.

Paste Datei1 Datei2 file3 ... etc ..fileN> fileN + 1 (oder was auch immer)

Das ist lesen Dateien Zeile für Zeile und paralelize Ausgang sequentiell Weg.

Das ist es. Es ist nicht sehr elegant, aber manchmal ist es sehr nützlich, bis Sie einen anderen Weg finden, um die Ergebnisse zu erhalten, die Sie suchen.

Hoffe, dass hilft

+0

Vielen Dank für den Austausch .. Ich denke, dass Paste nur funktioniert, wenn meine Daten sortiert sind, ist es nicht? Das Problem ist, dass ich die Sortierreihenfolge der Eingabe beibehalten muss. – Geroge

+0

Einfügen Befehl ändern Sie nicht die Reihenfolge der Daten als Daten in Datei sind, drucken sie Zeile für Zeile die verschiedenen Dateien verketten. Das heißt, erste Reihe file1, erste Reihe file2 ..... Wenn Ihre Daten vorher sortiert sind, ändert der Befehl paste das nicht. – Manu

Verwandte Themen