从解析循环中打印多行

时间:2016-07-13 14:12:16

标签: bash parsing sed

我已经编写了一个循环来解析文件中的几行并以更加用户友好的格式提取我想要的信息,但是我正在获取正在解析的字符串的副本。我认为我在使用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 )

我只想要标题和Taxa不同意(即第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

这是我写的代码(我怀疑它特别优雅或高效)

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

编辑:

我正在尝试处理的实际文件: https://drive.google.com/open?id=0Bz_H3y-7pX9FX0lZTWNBdlpIQmc

3 个答案:

答案 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"

答案 1 :(得分: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/'

也许第二步可以某种方式融入第一步,但我不确定如何。

答案 2 :(得分: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