efetch
尝试在 while 循环中使用特定工具(来自 NCBI E-utilities 套件)时,我遇到了一个非常奇怪的情况。这是我的输入文件,一个字符串列表,每行一个:
$ cat transcripts.list
NR_169596.1
NR_169595.1
NR_169594.1
我想efetch
使用这些字符串中的每一个作为参数来运行命令,所以我这样做:
$ 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>
这是一个结果,而不是三个,正如您从echo
运行的单个结果中看到的那样。但是,如果我使用错误的练习 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>
问:这怎么可能?即使特定程序中存在某种错误esearch
,也不应该影响循环,那么为什么shell在第一次迭代后退出?for
工作和while
失败怎么可能?他们在这里有什么不同?
更多细节。
在 esearch 命令前添加一个
echo
使循环按预期运行,因此这必须与特定esearch
命令相关(但如何打破 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
列表本身没有什么奇怪的,我可以用不同的列表重现它,并且没有隐藏字符:
$ 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
我在 bash 和 dash 中得到了相同的行为,因此它与 PIPEFAIL 或类似的东西无关。在任何情况下,命令的退出状态都是 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>
这发生在运行 Ubuntu、bash、版本 4.4.20(1)-release 的系统上。如果您想尝试一下,可以使用 安装该
efetch
工具。sudo apt install ncbi-entrez-direct
使用不同的语言在循环中按预期工作。例如,在
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>
这可能是因为
esearch
耗尽了它的标准输入;read
并且esearch
都从transcripts.list
.要解决此问题,请更改
esearch
的标准输入,例如esearch < /dev/null
.请参阅我正在逐行读取文件并运行 ssh 或 ffmpeg,只有第一行得到处理!在 Bash 常见问题解答中了解详细信息。