2016-07-13 3 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でありますそれは、特にエレガントなまたは効率的です)

#!/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 oubt:私はプロセスにしようとしている

実際のファイル: https://drive.google.com/open?id=0Bz_H3y-7pX9FX0lZTWNBdlpIQmc

+2

私はawkのようなテキスト処理言語を使用することをお勧めまたはその代わりにbashのでsedをしたい:

あなたがUNIXで欲しいものを行うには正しい方法は、標準のUNIX汎用のテキスト操作ツールのawkを使用することです。 – 123

+0

あなたのロジックが間違っています:あなたが処理しているすべての行に対して行を印刷しています。 「* Disagreement」行を処理した後にのみ印刷したいとします。 –

答えて

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

うん、何らかの理由で私はあなたが '[['。 – 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で行うことができますラインのペアを、マージする必要が第2段階でこのような出力をあなたに残し

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

:私は2つのステップを提案します

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

恐らく第2のステップは最初のステップに何らかの形で統合することができますが、どうすればよいかわかりません。

+0

ええ、私はsedの中で複数の正規表現に苦労しました。この解決策は近づくが、私が最終的に何をするかは、各ツリー比較のためにタブで区切られた行です。 ###の後ろに2行以上が残されます。 –

+0

申し訳ありませんが、十分注意して読んでいませんでした。更新しました。 –

+0

本当にありがとう。次のようにすれば、最終的に私は何を求めているのでしょうか?長くても長い一行で、sed -n -e 's /#* \(。* \)#* $/\ 1/p' -e /.*(\(。* \))$/\ 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