2016-07-13 4 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 : 라인 triplicated (다른 분류군의 목록을 제공하는 경우에, 그러나 별도의 하나라면 나는 아직 그 문제를 해결하지 않은) 곳이 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 

편집 :

내가 프로세스에 노력하고있어 실제 파일 : 가장이의 언어 만이 bash를 사용하지 않는 아마 https://drive.google.com/open?id=0Bz_H3y-7pX9FX0lZTWNBdlpIQmc

+2

내가 AWK와 같은 텍스트 처리 언어를 사용하는 것이 좋습니다 또는 그 대신 배쉬의 나오지 것 :

는 UNIX에서 원하는 일을 할 수있는 올바른 방법은 표준 UNIX 범용 텍스트 조작 도구 AWK를 사용하는 것입니다. – 123

+0

귀하의 스크립트에서 귀하의 논리가 잘못되었습니다 : 귀하가 처리하는 모든 라인에 대해 라인을 인쇄하고 있습니다. "* Disagreement"행을 처리 한 후에 만 ​​인쇄하려고합니다. –

답변

1

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

그래, 웬일인지 당신이'[['. – chepner

+0

나는 공간을 벗어나야한다고 생각해. 정규식을 var에 넣는 것이 좋습니다. – 123

1

순전히 sed으로 할 수 있습니다. 다만,

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 -e 's/#* \(.*\) #*$/\1/p' -e 's/.*(\(.*\))$/\1/p' < file.txt 

: 나는 두 단계를 제안한다 이전의 출력을 파이프하여 :

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

는 아마도 두 번째 단계는 어떻게 든 처음에 통합 할 수 있습니다,하지만 난 방법을 잘 모르겠어요.

+0

그래, 나는 sed에서 여러 정규식으로 고민했다. 이 솔루션은 가까워 지지만 궁극적으로는 각 트리 비교를위한 탭 구분선입니다. 이것은 모든 ###의 뒤에 두 줄 이상을 남겨 둡니다. –

+0

죄송합니다. 충분히주의하지 않았습니다. 업데이트 됨. –

+0

굉장히 감사합니다. 다음은 궁극적으로 긴 길다란 한 줄짜리에서 내가 원하는 것을 나에게 준다 :'sed -n -e 's/# * \ (. * \) # * $/\ 1/p'-e 's /.* (\ (. * \)) $/\ 1/p '

1

쉘은 텍스트를 조작하기위한 것이 아니라 도구 호출 순서를 지정하는 데 사용됩니다 (https://unix.stackexchange.com/questions/169716/why-is-using-a-shell-loop-to-process-text-considered-bad-practice 참조).

$ 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