在另一awk脚本中使用bash数组变量报错:无法打开文件,求解决
问题分析与解决
错误原因
- bash数组传递方式错误:你用
awk var="${array[@]}"传递数组时,bash会把数组元素展开为多个独立参数。比如数组包含foo bar,命令会被解析为awk var=foo bar '脚本' input.txt,此时awk会把bar当成要读取的输入文件,导致"找不到文件"的错误。 - awk语法错误:
heading[i] in var中的in操作符仅适用于awk的关联数组,而你传递的var是一个字符串,无法用in判断是否包含某个值。
解决方案
方案1:正确传递bash数组到awk,转为关联数组
先把bash数组转为字符串传递给awk,再在awk内部构建关联数组用于快速查找:
# 生成bash数组 array=($(awk 'NR>1 { print $1 }' < file.tsv)) # 用空格分隔数组元素(若元素含空格,可改用|等无冲突分隔符) arr_str="${array[*]}" # 传递给awk并构建关联数组 awk -v arr_str="$arr_str" ' BEGIN { # 拆分字符串为数组,构建允许集合 split(arr_str, temp_arr, " ") for (idx in temp_arr) { allowed[temp_arr[idx]] = 1 } } FNR==1 { for(i=1;i<=NF;i++){ heading[i]=$i } next } { for(i=2;i<=NF;i++){ if($i=="1" && heading[i] in allowed){ close(outFile) outFile=heading[i]".txt" print ">kmer"NR-1"\n"$1 >> outFile } } }' < input.txt
方案2:合并脚本,避免shell与awk的变量传递(推荐)
直接在同一个awk脚本中读取file.tsv构建允许集合,再处理input.txt,更高效且避免变量传递问题:
awk ' # 处理file.tsv,构建允许的heading集合 FILENAME == "file.tsv" { if (NR > 1) { allowed[$1] = 1 } next } # 处理input.txt FNR == 1 { for(i=1;i<=NF;i++){ heading[i]=$i } next } { for(i=2;i<=NF;i++){ if($i=="1" && heading[i] in allowed){ close(outFile) outFile=heading[i]".txt" print ">kmer"NR-1"\n"$1 >> outFile } } }' file.tsv input.txt
内容的提问来源于stack exchange,提问作者MK-1
相关产品推荐
相关产品推荐

