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