Eu tenho uma situação muito estranha ao tentar usar uma ferramenta específica ( efetch
do NCBI E-utilities suite) em um loop while. Este é meu arquivo de entrada, uma lista de strings, uma por linha:
$ cat transcripts.list
NR_169596.1
NR_169595.1
NR_169594.1
Eu quero executar o efetch
comando usando cada uma dessas strings como um argumento, então eu faço:
$ while read -r line; do echo "Line: $line"; esearch -db nucleotide -query "$line"; done < transcripts.list
Line: NR_169596.1
<ENTREZ_DIRECT>
<Db>nucleotide</Db>
<WebEnv>MCID_61bb689d20b59b3e2e2d405d</WebEnv>
<QueryKey>1</QueryKey>
<Count>1</Count>
<Step>1</Step>
</ENTREZ_DIRECT>
Este é um resultado único, não três, como você pode ver pelo único echo
que é executado. A mesma coisa funciona, no entanto, se eu usar um loop de prática ruim : for
$ for line in $(cat transcripts.list); do echo "Line: $line"; esearch -db nucleotide -query "$line"; done
Line: NR_169596.1
<ENTREZ_DIRECT>
<Db>nucleotide</Db>
<WebEnv>MCID_61bb68cabbe98560233344a7</WebEnv>
<QueryKey>1</QueryKey>
<Count>1</Count>
<Step>1</Step>
</ENTREZ_DIRECT>
Line: NR_169595.1
<ENTREZ_DIRECT>
<Db>nucleotide</Db>
<WebEnv>MCID_61bb68cad05f5825d75e3ace</WebEnv>
<QueryKey>1</QueryKey>
<Count>1</Count>
<Step>1</Step>
</ENTREZ_DIRECT>
Line: NR_169594.1
<ENTREZ_DIRECT>
<Db>nucleotide</Db>
<WebEnv>MCID_61bb68cb6bdec5435b5a41cb</WebEnv>
<QueryKey>1</QueryKey>
<Count>1</Count>
<Step>1</Step>
</ENTREZ_DIRECT>
Pergunta: Como isso é possível? Mesmo que haja algum tipo de bug no esearch
programa específico, isso não deve afetar o loop, então por que o shell está saindo após a primeira iteração? E como pode o for
trabalho e o while
fracasso? O que eles fazem de diferente aqui?
Mais alguns detalhes.
Adicionar um
echo
na frente do comando esearch faz com que o loop se comporte como esperado, então isso deve estar relacionado aoesearch
comando específico (mas como isso pode quebrar o loop do shell?):$ while read -r line; do echo esearch -db nucleotide -query "$line"; done < transcripts.list esearch -db nucleotide -query NR_169596.1 esearch -db nucleotide -query NR_169595.1 esearch -db nucleotide -query NR_169594.1
Não há nada de estranho na própria lista, posso reproduzi-la com listas diferentes e não há caracteres ocultos:
$ od -c transcripts.list 0000000 N R _ 1 6 9 5 9 6 . 1 \n N R _ 1 0000020 6 9 5 9 5 . 1 \n N R _ 1 6 9 5 9 0000040 4 . 1 \n 0000044
Eu recebo o mesmo comportamento em bash e dash, então não pode estar relacionado a coisas como PIPEFAIL ou algo assim. Em qualquer caso, o status de saída do comando é 0:
while read -r line; do esearch -db nucleotide -query "$line"; echo "EXIT: $?"; done < transcripts.list <ENTREZ_DIRECT> <Db>nucleotide</Db> <WebEnv>MCID_61bb69e71191d1185543b24a</WebEnv> <QueryKey>1</QueryKey> <Count>1</Count> <Step>1</Step> </ENTREZ_DIRECT>
Isso está acontecendo em um sistema rodando Ubuntu, bash, versão 4.4.20(1)-release. Você pode instalar a
efetch
ferramenta comsudo apt install ncbi-entrez-direct
, se quiser experimentar isso.Funciona conforme o esperado em um loop usando um idioma diferente. Por exemplo, em
perl
:$ perl -ne 'chomp;system("esearch -db nucleotide -query \"$_\"")' transcripts.list <ENTREZ_DIRECT> <Db>nucleotide</Db> <WebEnv>MCID_61bb6c68d8f66e4bb03f00e8</WebEnv> <QueryKey>1</QueryKey> <Count>1</Count> <Step>1</Step> </ENTREZ_DIRECT> <ENTREZ_DIRECT> <Db>nucleotide</Db> <WebEnv>MCID_61bb6c69947ca95fce4d4f0f</WebEnv> <QueryKey>1</QueryKey> <Count>1</Count> <Step>1</Step> </ENTREZ_DIRECT> <ENTREZ_DIRECT> <Db>nucleotide</Db> <WebEnv>MCID_61bb6c6a85c14642940393f9</WebEnv> <QueryKey>1</QueryKey> <Count>1</Count> <Step>1</Step> </ENTREZ_DIRECT>
Isso provavelmente ocorre porque
esearch
esgota sua entrada padrão;read
eesearch
ambos estão lendo detranscripts.list
.Para corrigir isso, altere
esearch
a entrada padrão de, por exemploesearch < /dev/null
, .Veja , estou lendo um arquivo linha por linha e executando ssh ou ffmpeg, apenas a primeira linha é processada! no Bash FAQ para detalhes.