web-dev-qa-db-ja.com

`while read`ループで複数のファイルを実行できないのはなぜですか?

このコマンドを180ファイルで実行したい:

cat kegg_random.tsv | while read line ; do
    echo "$line" | join -1 2 -2 1 -e"NA" -o1.1,0,2.2,2.3,2.4,2.5 -t $'\t' - kegg_sort_2020.out | shuf -n1 >> RM1_randomKO.tsv
  done

どうすればいいですか? bashで実行しようとしましたが、何かが間違っています:

#!/bin/bash
for f in *.txt; do 
  cat "$f" | while read line ; do 
  echo "$line" | 
  join -1 2 -2 1 -e"NA" -o1.1,0,2.2,2.3,2.4,2.5 -t $'\t' - kegg_sort_2020.out | 
  shuf -n1 > "${f%.tsv}" 
done

line 4: syntax error: unexpected end of file

ありがとうございました

3
Victor Borin

2番目のdoneがないため、forループは混乱します。修正:

for f in *.txt; do 
  while read line ; do 
      echo "$line" | 
      join -1 2 -2 1 -e"NA" -o1.1,0,2.2,2.3,2.4,2.5 -t $'\t' - kegg_sort_2020.out | 
      shuf -n1 >> "${f%.tsv}" 
  done < "$f"
done

注: catは不要でした>が必要な場合は>>の使用に注意してください。

それでも、上記のコードのロジックは少し混乱しているようです。 joinを1行で使用しても1行しか出力されないため、1行のファイルでshufを実行しても変更されません-役に立たないのです。 echoも実際には必要ありません。したがって、コードは次のように簡略化できます。

for f in *.txt; do 
  while read line ; do 
      join -1 2 -2 1 -e"NA" -o1.1,0,2.2,2.3,2.4,2.5 -t $'\t' \
        - kegg_sort_2020.out  <<<  "$line" 
  done < "$f"   >>  "${f%.tsv}"
done

入力ファイルの構造によっては、joinも不要な場合があります。賢明なreadで十分かもしれません。

4
agc