我想使用一组先前创建的变量来过滤名为 a.ped_snps.temp 的文件的列,并在 bash for 循环中使用 awk。
为此,我创建了 bash 变量:var_i_1、var_i_2、... var_i_n_blocks 作为下限; var_f_1, var_f_2, ... var_f_n_blocks 为上限。
请注意,前面提到的 n_blocks 是将使用 var_i_1 和 var_f_1 分隔的列创建的文件数,依此类推。我使用了以下脚本:
n_blocks=$(wc -l "a.temp" | awk '{print $1}') # number of blocks to be created, a.temp is the file with the number of blocks
for i in $(seq 1 1 $n_blocks) # to iterate of first to n_blocks
do
awk -v v_i="$var_i_$i" -v v_f="$var_f_$i" '{ # to declare variables of lower ($var_i_$i) and upper ($var_f_$i) bounds for each iteraction to awk command
for (i=v_i;i<=v_f;i++) {printf (i==1?"":FS)$i}; print "" # for statement to print all comlumns between specified in v_i and v_f variables in each iteraction
}' <a.ped_snps.temp > block_$i.txt # print one txt file with each block for each iteraction
done
此代码运行并以 for 命令中指定的正确迭代次数给出文件,但是,每个文件的输出中仅打印第一列。
当我仅使用 awk(如下)以及 var_i_1 和 var_f_1 bash 变量(分别具有先前存储的值 2 和 4)时,输出(block_1.txt)仅包含所需的列 $2、$3 和 $4,其他块依此类推。
awk -v v_i="$var_i_1" -v v_f="$var_f_1" '{ # declare variables of lower ($var_i_1) and upper ($var_f_1) bounds for first block (set of cloumns)
for (i=v_i;i<=v_f;i++) {printf (i==1?"":FS)$i}; print "" # for statement to print only comlumns between specified in v_i and v_f variables for first block
}' <a.ped_snps.temp > block_1.txt # print one txt file only with a set of columns specified in v_i and v_f variables
那么,有人可以帮助我在 bash 中实现这段代码吗?总之,我想使用之前在 bash 中的 awk 命令中创建的 bash 变量。
我希望我的解释是清楚的。
提前致谢。
答案1
看起来您希望$var_i_$i
扩展到 的值$var_i_1
,$var_i_2
依此类推 - 不幸的是事实并非如此。为了说明这一点,假设我们设置
$ var_i_1=23; var_i_2=45; var_i_3=67
然后
$ for i in $(seq 1 3); do awk -v v_i="$var_i_$i" 'BEGIN{print v_i}'; done
1
2
3
这里发生的情况是 shell 解析$var_i_$i
为$var_i_
连接有 $i
。因为$var_i_
可能未设置/为空,v_i
并且v_f
简单地继承循环索引的值i
。
有一些丑陋的方法可以实现您想要的间接方式,例如
$ for i in $(seq 1 3); do awk -v v_i="$(eval echo \${var_i_$i})" 'BEGIN{print v_i}'; done
23
45
67
然而,由于 bash 支持数组,一个更干净的解决方案是使用数组作为你的var_i
和var_f
值,例如。
$ var_i=(23 45 67)
然后(记住数组是零索引的)
$ for i in $(seq 0 2); do awk -v v_i="${var_i[i]}" 'BEGIN{print v_i}'; done
23
45
67