Bash while循环:防止第三方命令从stdin读取
Bash while loop: Preventing third-party commands to read from stdin
假设一个输入 table (intable.csv
) 在其第二列中包含 ID 号,以及一个新的输出 table (outlist.csv
),其中输入文件- 延长一栏 - 将逐行写入。
echo -ne "foo,NC_045043\nbar,NC_045193\nbaz,n.a.\nqux,NC_045054\n" > intable.csv
echo -n "" > outtable.csv
进一步假设使用一个或多个第三方命令(此处:esearch
、efetch
;Entrez Direct 的两个部分)来检索每个 ID 号的附加信息。此附加信息将形成输出的第三列 table.
while IFS="" read -r line || [[ -n "$line" ]]
do
echo -n "$line" >> outtable.csv
NCNUM=$(echo "$line" | awk -F"," '{print }')
if [[ $NCNUM == NC_* ]]
then
echo "$NCNUM"
RECORD=$(esearch -db nucleotide -query "$NCNUM" | efetch -format gb)
echo "$RECORD" | grep "^LOCUS" | awk '{print ","}' | \
tr -d "\n" >> outtable.csv
else
echo ",n.a." >> outtable.csv
fi
done < intable.csv
为什么 while 循环只遍历上述代码下的第一个输入 table 条目,而如果代码行以 开头,它会遍历所有输入 table 条目RECORD 和 echo "$RECORD" 被注释掉了?我该如何纠正这种行为?
如果 esearch
从标准输入读取,就会发生这种情况。它将继承 while
循环的输入重定向,因此它将消耗输入文件的其余部分。
解决方案是将标准输入重定向到别处,例如/dev/null
.
while IFS="" read -r line || [[ -n "$line" ]]
do
echo -n "$line" >> outtable.csv
NCNUM=$(echo "$line" | awk -F"," '{print }')
if [[ $NCNUM == NC_* ]]
then
echo "$NCNUM"
RECORD=$(esearch -db nucleotide -query "$NCNUM" </dev/null | efetch -format gb)
echo "$RECORD" | grep "^LOCUS" | awk '{print ","}' | \
tr -d "\n" >> outtable.csv
else
echo ",n.a." >> outtable.csv
fi
done < intable.csv
假设一个输入 table (intable.csv
) 在其第二列中包含 ID 号,以及一个新的输出 table (outlist.csv
),其中输入文件- 延长一栏 - 将逐行写入。
echo -ne "foo,NC_045043\nbar,NC_045193\nbaz,n.a.\nqux,NC_045054\n" > intable.csv
echo -n "" > outtable.csv
进一步假设使用一个或多个第三方命令(此处:esearch
、efetch
;Entrez Direct 的两个部分)来检索每个 ID 号的附加信息。此附加信息将形成输出的第三列 table.
while IFS="" read -r line || [[ -n "$line" ]]
do
echo -n "$line" >> outtable.csv
NCNUM=$(echo "$line" | awk -F"," '{print }')
if [[ $NCNUM == NC_* ]]
then
echo "$NCNUM"
RECORD=$(esearch -db nucleotide -query "$NCNUM" | efetch -format gb)
echo "$RECORD" | grep "^LOCUS" | awk '{print ","}' | \
tr -d "\n" >> outtable.csv
else
echo ",n.a." >> outtable.csv
fi
done < intable.csv
为什么 while 循环只遍历上述代码下的第一个输入 table 条目,而如果代码行以 开头,它会遍历所有输入 table 条目RECORD 和 echo "$RECORD" 被注释掉了?我该如何纠正这种行为?
如果 esearch
从标准输入读取,就会发生这种情况。它将继承 while
循环的输入重定向,因此它将消耗输入文件的其余部分。
解决方案是将标准输入重定向到别处,例如/dev/null
.
while IFS="" read -r line || [[ -n "$line" ]]
do
echo -n "$line" >> outtable.csv
NCNUM=$(echo "$line" | awk -F"," '{print }')
if [[ $NCNUM == NC_* ]]
then
echo "$NCNUM"
RECORD=$(esearch -db nucleotide -query "$NCNUM" </dev/null | efetch -format gb)
echo "$RECORD" | grep "^LOCUS" | awk '{print ","}' | \
tr -d "\n" >> outtable.csv
else
echo ",n.a." >> outtable.csv
fi
done < intable.csv