2016-07-13 21 views
0

Ich habe eine Schleife geschrieben, um mehrere Zeilen in einer Datei zu analysieren und die Informationen, die ich möchte, in einem benutzerfreundlicheren Format zu extrahieren, aber ich erhalte Duplikate der Strings, die ich analysiere gedruckt. Ich denke, ich mache etwas falsch (und dumm) in meiner Verwendung von echo | sed Befehle, aber ich kann es jetzt nicht sehen .. kann jemand darauf hinweisen, wo ich falsch liege?mehrere Zeilen aus einer Parsing-Schleife drucken

Datei Aussehen zu analysieren (verkürzt) wie folgt aus:

##################################### topd Tree0 - Tree6 ####################################### 
* Percentage of taxa in common: 100.0% 
* Split Distance [differents/possibles]: 0.461538461538462 [ 12/26 ] 
* Disagreement [ taxa disagree/all taxa ]: [ 9/16 ], New Split Distance: 0, Taxa disagree: (PAUlopT PAKU2 PAKlopT PAUU4 PLTU1 PLTU3 PLTU4 PLTcif PLTlopT) 

##################################### topd Tree0 - Tree7 ####################################### 
* Percentage of taxa in common: 100.0% 
* Split Distance [differents/possibles]: 0.538461538461538 [ 14/26 ] 
* Disagreement [ taxa disagree/all taxa ]: [ 9/16 ], New Split Distance: 0, Taxa disagree: (PAKU2 PAKlopT PAUU4 PAUlopT PLTU1 PLTU2 PLTU3 PLTU4 PLTlopT) 

##################################### topd Tree0 - Tree8 ####################################### 
* Percentage of taxa in common: 100.0% 
* Split Distance [differents/possibles]: 0.230769230769231 [ 6/26 ] 
* Disagreement [ taxa disagree/all taxa ]: [ 4/16 ], New Split Distance: 0, Taxa disagree: (PLTU1 PLTU2 PLTU3 PLTU4) 

Und ich will nur die Header und die Taxa nicht einverstanden sind (dh die Linien 1 und Ende der Zeile 4)

Aber ich bin immer dies, wo Linien verdreifachten (und in einigen Fällen verschiedene Taxa Listen geben, aber ich habe nicht angesprochen, dieses Problem noch, wenn es einen separaten ist):

Tree0 - Tree6 PAKlopT PAUlopT PLTU1 PLTU2 PLTU3 PLTU4 PLTlopT 
Tree0 - Tree6 PAKlopT PAUlopT PLTU1 PLTU2 PLTU3 PLTU4 PLTlopT 
Tree0 - Tree6 PAKlopT PAUlopT PLTU1 PLTU2 PLTU3 PLTU4 PLTlopT 
Tree0 - Tree6 PAUlopT PAKU2 PAKlopT PAUU4 PLTU1 PLTU3 PLTU4 PLTcif PLTlopT 
Tree0 - Tree6 PAUlopT PAKU2 PAKlopT PAUU4 PLTU1 PLTU3 PLTU4 PLTcif PLTlopT 
Tree0 - Tree7 PAUlopT PAKU2 PAKlopT PAUU4 PLTU1 PLTU3 PLTU4 PLTcif PLTlopT 
Tree0 - Tree7 PAUlopT PAKU2 PAKlopT PAUU4 PLTU1 PLTU3 PLTU4 PLTcif PLTlopT 
Tree0 - Tree7 PAUlopT PAKU2 PAKlopT PAUU4 PLTU1 PLTU3 PLTU4 PLTcif PLTlopT 
Tree0 - Tree7 PAKU2 PAKlopT PAUU4 PAUlopT PLTU1 PLTU2 PLTU3 PLTU4 PLTlopT 
Tree0 - Tree7 PAKU2 PAKlopT PAUU4 PAUlopT PLTU1 PLTU2 PLTU3 PLTU4 PLTlopT 
Tree0 - Tree8 PAKU2 PAKlopT PAUU4 PAUlopT PLTU1 PLTU2 PLTU3 PLTU4 PLTlopT 
Tree0 - Tree8 PAKU2 PAKlopT PAUU4 PAUlopT PLTU1 PLTU2 PLTU3 PLTU4 PLTlopT 
Tree0 - Tree8 PAKU2 PAKlopT PAUU4 PAUlopT PLTU1 PLTU2 PLTU3 PLTU4 PLTlopT 
Tree0 - Tree8 PLTU1 PLTU2 PLTU3 PLTU4 
Tree0 - Tree8 PLTU1 PLTU2 PLTU3 PLTU4 

und das ist der Code, den ich geschrieben habe (I d oubt es ist besonders elegant oder effizient)

#!/bin/bash 

file="$1" 
### 

while read LINE ; 
do 
if [[ $LINE == "#"* ]] 
    then 
    header=$(echo $LINE | sed 's/\#//g' | sed 's/\ topd\ //g') 
fi 
if [[ $LINE == "* Disagreement"* ]] ; 
    then 
    taxa=$(echo $LINE | sed 's/.*(\(\ .*\ \))/\1/' | grep "^ " |sed 's/\ /\t/g') 
fi 

echo "$header""$taxa" 

done < $file 

EDIT:

Die eigentliche Datei, die ich zu verarbeiten bin versucht: https://drive.google.com/open?id=0Bz_H3y-7pX9FX0lZTWNBdlpIQmc

+2

Ich würde vorschlagen, eine Textverarbeitungssprache wie awk oder sed statt bash verwenden. – 123

+0

Ihre Logik ist falsch in Ihrem Skript: Sie drucken eine Zeile für jede Zeile, die Sie verarbeiten. Sie möchten erst drucken, nachdem Sie eine Zeile "* Widerspruch" verarbeitet haben. –

Antwort

1

bash wahrscheinlich nicht die beste Sprache für diese, aber bash mit Der Abgleich mit regulären Ausdrücken wird es viel einfacher machen.

#!/bin/bash 

file="$1" 
### 

header_regex='# topd (.*) #' 
taxa_regex='Taxa disagree: \((.*)\)' 
while read line; do 
    if [[ $line =~ $header_regex ]]; then 
    header=${BASH_REMATCH[1]} 
    elif [[ $line =~ $taxa_regex ]]; then 
    taxa=${BASH_REMATCH[1]} 
    echo "$header $taxa" 
    fi  
done < "$file" 
+0

Vielleicht möchten Sie diese '#' zu entkommen. – 123

+0

Yup, aus irgendeinem Grund dachte ich, du könntest keinen Kommentar in '[['. – chepner

+0

Ich denke, du musst auch Räumen entkommen. Könnte besser sein, die Regex in eine Var zu setzen. – 123

1

Sie können es rein mit sed tun. Ich schlage vor, zwei Schritte:

sed -n -e 's/#* \(.*\) #*$/\1/p' -e 's/.*(\(.*\))$/\1/p' < file.txt 

, dass Sie mit einem Ausgang wie dies läßt:

topd Tree0 - Tree6 
PAUlopT PAKU2 PAKlopT PAUU4 PLTU1 PLTU3 PLTU4 PLTcif PLTlopT 
topd Tree0 - Tree7 
PAKU2 PAKlopT PAUU4 PAUlopT PLTU1 PLTU2 PLTU3 PLTU4 PLTlopT 
topd Tree0 - Tree8 

In einem zweiten Schritt können Sie die Paare von Linien zu verschmelzen haben, die auch mit sed getan werden kann, nur durch Verlegen der vorherigen Ausgabe:

... | sed 'N;s/\n/\t/' 

Vielleicht kann der zweite Schritt irgendwie in die erste integriert werden, aber ich bin mir nicht sicher, wie.

+0

Yeah Ich hatte Probleme mit mehreren Regexs in sed (noch nie wirklich getan). Diese Lösung nähert sich, aber letztendlich möchte ich eine tabulatorgetrennte Zeile für jeden Baumvergleich angeben. Dies hinterlässt alle ### 's hinter und über 2 Zeilen. –

+0

Sorry, habe nicht vorsichtig genug gelesen. Aktualisiert. –

+0

Ja, vielen Dank. Die folgende schließlich gibt mir, was ich gesucht werden, in einem wenn auch langwierigen Einzeiler: '(. * \) S/# * \ # * $/\ 1/p' 'sed -n -e -e‚s /.* (\ (. * \)) $/\ 1/p '

1

Shell ist nicht für die Manipulation von Text, es ist für Sequencing Aufrufe an Werkzeuge, siehe https://unix.stackexchange.com/questions/169716/why-is-using-a-shell-loop-to-process-text-considered-bad-practice.

Der richtige Weg zu tun, was Sie in UNIX wollen, ist die Standard-UNIX-Allzweck-Textmanipulation Tool awk zu verwenden:

$ cat tst.awk 
/####/ { hdr = $3 " - " $5 } 
/Disagreement/ { gsub(/.*\(*| *\).*/,""); print hdr, $0 } 

$ awk -f tst.awk file 
Tree0 - Tree6 PAUlopT PAKU2 PAKlopT PAUU4 PLTU1 PLTU3 PLTU4 PLTcif PLTlopT 
Tree0 - Tree7 PAKU2 PAKlopT PAUU4 PAUlopT PLTU1 PLTU2 PLTU3 PLTU4 PLTlopT 
Tree0 - Tree8 PLTU1 PLTU2 PLTU3 PLTU4 
Verwandte Themen