Bash双层循环无法正常运行问题求助
排查并修正你的Bash双层循环代码问题
我帮你梳理了这段代码里的几个关键错误,咱们一步步来修复,让它正常运行:
1. 第一个for循环的语法错误
Bash要求for循环的遍历列表和do之间必须用分号;或者换行分隔,你原来的代码直接把do跟在列表后面,语法不合法:
# 错误写法 for i in *CCDSxBaseCov.bed do # 正确写法(二选一) for i in *CCDSxBaseCov.bed; do # 或者换行写do for i in *CCDSxBaseCov.bed do
2. 变量赋值的冗余括号与低效写法
你提取样本标识SM时用了冗余的括号,而且调用sed有点多余——Bash本身支持字符串后缀删除,更高效:
# 错误写法(冗余括号+调用外部命令) SM=`(echo $i | sed 's/.bed//g')`; # 推荐写法1(用$()代替反引号,加双引号防空格) SM=$(echo "$i" | sed 's/.bed//g') # 推荐写法2(Bash内置字符串操作,无需外部命令) SM="${i%.bed}"
3. 缺失循环闭合的done语句
你的代码只写了两个循环的开头,却没有用done来闭合循环,这会直接导致语法报错。需要在代码末尾添加两个done,分别对应内层染色体循环和外层文件循环。
4. 整数除法的“除以零”风险
当某个染色体在bed文件里没有匹配行时,bases会变成0,直接执行avercov=$(($cov/$bases))会触发“除以零”的错误。可以先判断bases是否大于0,再计算平均覆盖度:
if [ "$bases" -gt 0 ]; then avercov=$((cov / bases)) else avercov=0 echo "Warning: No bases found for chr$chr" fi
5. 命令替换的冗余括号
bases和cov赋值时的括号是多余的,而且grep的模式最好加双引号,避免特殊字符干扰:
# 错误写法 bases=`(grep chr$chr "${SM}_hg19_EXONSxBaseCov.bed" | wc -l)`; # 正确写法 bases=$(grep "chr$chr" "${SM}_hg19_EXONSxBaseCov.bed" | wc -l)
修正后的完整代码
for i in *CCDSxBaseCov.bed; do SM="${i%.bed}" echo "$SM" for chr in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 X Y M; do echo "-- chr$chr --" bed_file="${SM}_hg19_EXONSxBaseCov.bed" # 先检查文件是否存在,避免报错 if [ ! -f "$bed_file" ]; then echo "Error: File $bed_file does not exist" continue fi bases=$(grep "chr$chr" "$bed_file" | wc -l) echo "EXONS target length=$bases" cov=$(grep "chr$chr" "$bed_file" | awk '{sum+=$3} END {print sum+0}') # sum+0确保空输出时返回0 echo "sum EXONS bases coverage=$cov" if [ "$bases" -gt 0 ]; then avercov=$((cov / bases)) else avercov=0 echo "Warning: No data for chr$chr" fi echo "EXONS average coverage=$avercov" done done
额外加了文件存在检查和awk的sum+0处理,避免文件不存在或者无匹配行时输出空值导致的问题。
内容的提问来源于stack exchange,提问作者Emma Athan
相关产品推荐
相关产品推荐

