提问人:pooch 提问时间:6/14/2023 最后编辑:chorobapooch 更新时间:6/14/2023 访问量:41
“同时读 -r 行;do“无法识别计数器变量
"while read -r line; do" not recognizing counter variable
问:
我有可用于处理每一行文件的代码,但是当我尝试在 while 循环中使用计数器变量将迭代限制为整数“n”时,它不再有效。
这是我的代码:
# Output file for biallelic SNPs
output_file=${SNAPTMP}/SNAP.proxy.ld.gwas.bestproxy.out
# Loop over the files
for file in ${SNAPTMP}/SNAP.*.proxy.ld.gwas.bestproxy; do
echo "Processing file: $file"
counter=0
# Process each line of the file
while read -r line; do
# Extract the 6th field from the line
field=$(echo "$line" | awk '{print $6}')
# Check if the field is a biallelic SNP
if [[ $(is_biallelic "$field") -eq 1 ]]; then
# Append the line to the output file
echo "$line" >> "$output_file"
fi
done < "$file"
done
这可以正常工作并按预期工作,并使以下输出:
[-----.-------@---- SNAPPY]$ cat proxy/SNAPTMP/SNAP.proxy.ld.gwas.bestproxy.out
6 30656398 rs2249059 6 30609835 rs78802957 1 46563
6 30656398 rs2249059 6 30609835 rs78802957 1 46563
6 30656398 rs2249059 6 30607289 rs142580331 1 49109
6 30656398 rs2249059 6 30607189 rs113520162 1 49209
6 30656398 rs2249059 6 30607173 rs111808357 1 49225
6 30656398 rs2249059 6 30606141 rs112927484 1 50257
6 30656398 rs2249059 6 30604733 rs147842052 1 51665
...
(此文件中有 49 行)
我的问题是我希望它只将每个文件打印“n”行,该文件在字段 6 上拥有双等位基因 SNP 到我的输出文件。我将代码修改为:
n=4
snp_db_file=/project/richards/ethan.kreuzer/snp156.db
# Output file for biallelic SNPs
output_file=${SNAPTMP}/SNAP.proxy.ld.gwas.bestproxy.out
# Loop over the files
for file in ${SNAPTMP}/SNAP.*.proxy.ld.gwas.bestproxy; do
echo "Processing file: $file"
counter=0
# Process each line of the file
while read -r line; do
# Extract the 6th field from the line
field=$(echo "$line" | awk '{print $6}')
# Check if the field is a biallelic SNP
if [[ $(is_biallelic "$field") -eq 1 ]]; then
# Append the line to the output file
echo "$line" >> "$output_file"
((counter++))
if ((counter >= n)); then
break # Break the inner loop after n iterations
fi
fi
done < "$file"
done
但现在我得到了:
[-----.-------@---- SNAPPY]$ cat proxy/SNAPTMP/SNAP.proxy.ld.gwas.bestproxy.out
6 30656398 rs2249059 6 30609835 rs78802957 1 46563
这似乎是基本代码,所以我真的不确定我做错了什么。
答:
0赞
chepner
6/14/2023
#1
你不需要计数器。让循环输出所有行,并仅将其中第一行输出到输出文件。退出时,循环也将在第一次尝试将行写入现在关闭的管道时。while
head
n
head
for file in ${SNAPTMP}/SNAP.*.proxy.ld.gwas.bestproxy; do
echo "Processing file: $file"
# Process each line of the file
while read -r line; do
field=$(echo "$line" | awk '{print $6}')
[[ $(is_biallelic "$field") -eq 1 ]] && echo "$line"
done < "$file" | head -n "$n" >> "$output_file"
done
检查是否可以使用 的退出状态而不是其输出来确定是否输出,这样就可以编写类似 的内容is_biallelic
$line
is_biallelic "$field" && echo "$line"
整个循环也可能被替换为一个可以根据需要调用的脚本,而不是仅仅为了提取一个字段而在每一行上运行。它可以像while
awk
is_biallelic
awk
awk 'system("is_biallelic $6")' "$file" >> "$output_file"
评论
0赞
Charles Duffy
6/14/2023
在我看来,该调用中有一个 shell 注入,除非我误解了如何扩展。我错过了什么吗?system()
$6
0赞
chepner
6/14/2023
你错过了我没有费心检查外壳注入:)(另外,我无论如何都没有测试它;最后一个命令应该被视为伪代码,它暗示了让运行而不是让 shell 运行它的想法。awk
awk
is_biallelic
0赞
chepner
6/14/2023
(尽管安全地这样做可能需要一个可以移植到 的 shell 函数;我自己很少使用外部命令。is_biallelic
awk
awk
评论
set -xv
read
read
set -x
set -o errexit
set -e
((counter++))
counter
set -o errexit
field=$(echo "$line" | awk '{print $6}')
awk
read -r f1 f2 f3 f4 f5 field frest <<< "$line"