Se você insistir em fazer isso com awk
:
( echo -n '/^>('; paste -sd\| - <species_list | tr -d '\n'; echo -n ')/,/^$/' ) | \
awk -f - moldata
Eu tenho a seguinte entrada:
cat moldata
>species_1
?????????CACTTGGArGGTGGAGCCAAGAAGGTTATTATTTCTGCTCCCAGTGCTGACGCGCCCATGTACGTGGTC
TGTCAACCTCGATTCTTATGACCCATCTGCTAAGGTCATTTCGAATGCTTCCTGCACCACCAACTGCCTCGCTCCCCT
>species_2
CCAAGGTCATCCATGACAACTTTGAGATCATTGAAGGCCTGATGACCACTGTACACGCCACCACCGCTACTCAGAAGA
GTCGACGGACCTTCCGGTAAACTCTGGCGTGATGGTCGTGGCGCTCAACAAAACATCATTCCCGCCTCTACTGGTGCT
>species_3
CAAAGCCGTAGGCAAAGTCATTCCTGCTCTCAACGGTAAACTGACTGGCATGGCCTTCCGTGTTCCCGTTCCAAATGT
CGGTTGTGGATCTTACTGTTCGCyTGGGAAAACCAGCCTCTTATGACrCCATTAAACAGAAGGTCAAGGAGGCTGCTG
>species_4
GGTCCTTTGAAGGGTATTCTTGGATACACCGAAGATCAAGTTGTGTCCACCGACTTTGTTGGAGACACACACTCTTCA
CTTTGACGCTGCTGCTGGTATCTCCCTCAACGATAACTTCGTCAAACTTATCAGCTGGTACGACAATGAATATGGATA
>species_5
GTTCCGCAAAGCTCAATGCCCTATTGTTGAGCGTCTGACCAATTCTCTCATGATGCATGGCCGCAACAACGGCAAGAA
TGATGGCAGTGCGAATTGTTAAGCATGCCTTTGAAATCATCCACCTTCTGACTGGAGAGAATCCTCTTCAAGTACTCG
e eu gostaria de recuperar da moldata o registro da espécie (nome da espécie + o bloco de linhas que a segue até o próximo registro de espécie) para as espécies listadas aqui:
cat species_list
species_1
species_3
species_5
para obter a seguinte saída:
cat output
>species_1
?????????CACTTGGArGGTGGAGCCAAGAAGGTTATTATTTCTGCTCCCAGTGCTGACGCGCCCATGTACGTGGTC
TGTCAACCTCGATTCTTATGACCCATCTGCTAAGGTCATTTCGAATGCTTCCTGCACCACCAACTGCCTCGCTCCCCT
>species_3
CAAAGCCGTAGGCAAAGTCATTCCTGCTCTCAACGGTAAACTGACTGGCATGGCCTTCCGTGTTCCCGTTCCAAATGT
CGGTTGTGGATCTTACTGTTCGCyTGGGAAAACCAGCCTCTTATGACrCCATTAAACAGAAGGTCAAGGAGGCTGCTG
>species_5
GTTCCGCAAAGCTCAATGCCCTATTGTTGAGCGTCTGACCAATTCTCTCATGATGCATGGCCGCAACAACGGCAAGAA
TGATGGCAGTGCGAATTGTTAAGCATGCCTTTGAAATCATCCACCTTCTGACTGGAGAGAATCCTCTTCAAGTACTCG
Eu tentei fazer awk
funcionar em um loop while:
while read line;
do
if grep -q "$line" moldata;
then echo $line | awk -v line=${line} 'BEGIN {RS=">"} /line/ {print $0}' moldata >> output;
else echo "$line not found";
fi;
done < species_list
Eu li sobre a opção getline
com awk
, mas não consegui fazer isso funcionar.
Se você insistir em fazer isso com awk
:
( echo -n '/^>('; paste -sd\| - <species_list | tr -d '\n'; echo -n ')/,/^$/' ) | \
awk -f - moldata
Para um único registro, você pode fazer algo assim:
awk '/species_1/{print;while (getline line){if(line !~/species/) print line; else break} }' input.txt
>species_1
?????????CACTTGGArGGTGGAGCCAAGAAGGTTATTATTTCTGCTCCCAGTGCTGACGCGCCCATGTACGTGGTC
TGTCAACCTCGATTCTTATGACCCATCTGCTAAGGTCATTTCGAATGCTTCCTGCACCACCAACTGCCTCGCTCCCCT
Com vários itens, você pode querer algo ao longo destas linhas:
$ while IFS= read -r line
> do
> awk -v spec="$line" '$0~spec{print;while (getline line){if(line !~/species/) print line; else break} }' input.txt
> done < species.txt
>species_1
?????????CACTTGGArGGTGGAGCCAAGAAGGTTATTATTTCTGCTCCCAGTGCTGACGCGCCCATGTACGTGGTC
TGTCAACCTCGATTCTTATGACCCATCTGCTAAGGTCATTTCGAATGCTTCCTGCACCACCAACTGCCTCGCTCCCCT
>species_3
CAAAGCCGTAGGCAAAGTCATTCCTGCTCTCAACGGTAAACTGACTGGCATGGCCTTCCGTGTTCCCGTTCCAAATGT
CGGTTGTGGATCTTACTGTTCGCyTGGGAAAACCAGCCTCTTATGACrCCATTAAACAGAAGGTCAAGGAGGCTGCTG
>species_5
GTTCCGCAAAGCTCAATGCCCTATTGTTGAGCGTCTGACCAATTCTCTCATGATGCATGGCCGCAACAACGGCAAGAA
TGATGGCAGTGCGAATTGTTAAGCATGCCTTTGAAATCATCCACCTTCTGACTGGAGAGAATCCTCTTCAAGTACTCG
Sabendo que os dados no exemplo do OP são sempre duas linhas após o nome da espécie, podemos carregar os nomes das espécies em species.txt
no array e, em seguida, usar o loop para ler uma linha duas vezes e imprimi-la.
$ awk 'FNR==NR{species[$0]}; NR!=FNR{ sub(/>/,"");if ($0 in species){ print $0; for(i=0;i<=1;i++) {getline data;print data} }}' species.txt input.txt
species_1
?????????CACTTGGArGGTGGAGCCAAGAAGGTTATTATTTCTGCTCCCAGTGCTGACGCGCCCATGTACGTGGTC
TGTCAACCTCGATTCTTATGACCCATCTGCTAAGGTCATTTCGAATGCTTCCTGCACCACCAACTGCCTCGCTCCCCT
species_3
CAAAGCCGTAGGCAAAGTCATTCCTGCTCTCAACGGTAAACTGACTGGCATGGCCTTCCGTGTTCCCGTTCCAAATGT
CGGTTGTGGATCTTACTGTTCGCyTGGGAAAACCAGCCTCTTATGACrCCATTAAACAGAAGGTCAAGGAGGCTGCTG
species_5
GTTCCGCAAAGCTCAATGCCCTATTGTTGAGCGTCTGACCAATTCTCTCATGATGCATGGCCGCAACAACGGCAAGAA
TGATGGCAGTGCGAATTGTTAAGCATGCCTTTGAAATCATCCACCTTCTGACTGGAGAGAATCCTCTTCAAGTACTCG
declare -a list
readarray list < /path/to/species_list
for species in ${list[@]}; do
sed -ne "/$species/,/^\$/p" moldata
done
Normalmente, é possível citar um script sed
embutido, mas estamos usando uma variável shell para procurar seus dados e, portanto, ter que escapar do $
para evitar que o shell tente analisá-lo. / p>
"Por uma dispensação especial, uma string vazia como o valor de RS indica que os registros são separados por uma ou mais linhas em branco", então
awk ' BEGIN { OFS=FS="\n"; RS=""; ORS="\n\n" }
FNR==NR { for (k=0;k<NF;) ++species[">"$++k] }
$1 in species
' species_list moldata
$ awk '
NR==FNR{ sp[$0]; next } # this is for reading species data into sp array
/species/ { # from this point for moldata's lines
if (substr($0,2) in sp) { # if the read line match with data in sp array
print # first print title
while(getline > 0) { # and then read until blank line and print
if (NF == 0) { print ""; break }
print
}
}
}
' species_list moldata
>species_1
?????????CACTTGGArGGTGGAGCCAAGAAGGTTATTATTTCTGCTCCCAGTGCTGACGCGCCCATGTACGTGGTC
TGTCAACCTCGATTCTTATGACCCATCTGCTAAGGTCATTTCGAATGCTTCCTGCACCACCAACTGCCTCGCTCCCCT
>species_3
CAAAGCCGTAGGCAAAGTCATTCCTGCTCTCAACGGTAAACTGACTGGCATGGCCTTCCGTGTTCCCGTTCCAAATGT
CGGTTGTGGATCTTACTGTTCGCyTGGGAAAACCAGCCTCTTATGACrCCATTAAACAGAAGGTCAAGGAGGCTGCTG
>species_5
GTTCCGCAAAGCTCAATGCCCTATTGTTGAGCGTCTGACCAATTCTCTCATGATGCATGGCCGCAACAACGGCAAGAA
TGATGGCAGTGCGAATTGTTAAGCATGCCTTTGAAATCATCCACCTTCTGACTGGAGAGAATCCTCTTCAAGTACTCG