2016-07-13 2 views
0

Я написал цикл, чтобы разобрать несколько строк в файле и извлечь информацию, которую я хочу, в более удобном для пользователя формате, но я получаю дубликаты строк, которые я разбираю, распечатаны. Я думаю, что я делаю что-то неправильно (и глупо) при использовании команд echo | sed, но я просто не могу его увидеть сейчас .. может ли кто-нибудь указать, где я ошибаюсь?Печать нескольких строк из цикла синтаксического анализа

файла разобрать внешний вид (в сокращенном виде), как это:

##################################### 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) 

И я хочу только заголовки и таксонов не согласен (то есть строки 1 и конец строки 4)

Но я получаю это где линии утроенные (а в некоторых случаях, дающих различные списки таксонов, но я не затрагивал эту проблему еще, если это отдельно) и:

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 

и это код, который я написал (I d oubt это особенно элегантно или эффективно)

#!/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:

Фактический файл Я пытаюсь процесс: https://drive.google.com/open?id=0Bz_H3y-7pX9FX0lZTWNBdlpIQmc

+2

Я предложил бы использовать язык обработки текста, как AWK или SED вместо Баша. – 123

+0

Ваша логика в вашем скрипте неверна: вы печатаете строку для каждой обрабатываемой вами строки. Вы хотите печатать только после того, как вы обработали строку «* Разъяснение». –

ответ

1

bash, вероятно, не самый лучший язык для этого, но с использованием bash сопоставление регулярных выражений сделает его намного проще.

#!/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

Вы можете избежать этих '#'. – 123

+0

Yup, по какой-то причине я думал, что вы не можете начать комментарий внутри '[['. – chepner

+0

Я думаю, вам также нужно избегать пробелов. Может быть, лучше поставить регулярное выражение в var. – 123

1

Вы можете сделать это чисто с sed. Я предлагаю два шага:

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

Это оставляет вас с выходом, как это:

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 

Во втором шаге вы должны объединить пары линий, которые также могут быть сделаны с sed, просто по конвейеру предыдущий вывод:

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

Возможно, второй этап может быть как-то интегрировать в первый, но я не знаю, как.

+0

Да, я боролся с несколькими регулярными выражениями в sed (никогда не делал этого раньше). Это решение приближается, но то, что я в конечном счете, это строка с разделителями табуляции для каждого сравнения деревьев. Это оставляет все ### позади и над 2 строками. –

+0

Извините, недостаточно внимательно прочитал. Обновлено. –

+0

Да большое спасибо. Следующее в конечном итоге дает мне то, что я искал бы, хотя бы длинный однострочный: 'sed -n -e 's/# * \ (. * \) # * $/\ 1/p' -e 's /.* (\ (. * \)) $/\ 1/p '

1

Shell не предназначен для обработки текста, это для последовательности вызовов инструментов, см. https://unix.stackexchange.com/questions/169716/why-is-using-a-shell-loop-to-process-text-considered-bad-practice.

Правильный способ сделать то, что вы хотите в UNIX является использование стандартных UNIX общего назначения текст манипуляции инструмента AWK:

$ 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 
Смежные вопросы