最初の反復後にこのwhileループが終了するのはなぜですか?

最初の反復後にこのwhileループが終了するのはなぜですか?

whileループで特定のツール(NCBI Electronics Utility Suiteの)を使用しようとしているesearch間、非常に奇妙な状況に直面しました。これは、1行に1つずつ文字列のリストである入力ファイルです。

$ cat transcripts.list 
NR_169596.1
NR_169595.1
NR_169594.1

各文字列を引数として使用してコマンドを実行したいesearchので、次のようにします。

$ 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単一の結果を実行することでわかるように、これは3つではなく1つの結果です。しかし、私が使うと悪い習慣 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ループに影響を与えてはいけませんが、なぜ最初の反復後にシェルが終了するのですか?for仕事はどのようにwhile失敗することができますか?ここで彼らは何を変えていますか?


詳細については。

  1. esearchコマンドの前に追加すると、echoループは期待どおりに機能するため、これはesearch特定のコマンドに関連する必要があります(しかし、これはどのようにシェルループを中断しますか?)。

    $ 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
    
  2. リスト自体に奇妙なことはありません。隠し文字なしで別のリストに再現できます。

    $ 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
    
  3. BashとDashで同じ動作が発生するため、PIPEFAILまたはそのようなものに関連することはできません。このコマンドの終了状態は何があってもゼロです。

     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>
    
  4. これは、Ubuntu、bash、バージョン4.4.20(1)リリースを実行しているシステムで発生します。一度試したい場合は、を使ってefetchツールをインストールできます。sudo apt install ncbi-entrez-direct

  5. ループで異なる言語を使用すると、期待どおりに機能します。たとえば、次のようになります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>
    

ベストアンサー1

これはおそらくesearch標準入力がすべて消費されたためです。readどちらもesearch読んでいますtranscripts.list

この問題を解決するには、esearch標準入力を次に変更します。例えば esearch < /dev/null

バラよりファイルを1行ずつ読み、sshまたはffmpegを実行すると、最初の行だけが処理されます。詳細については、Bash FAQをご覧ください。

おすすめ記事