如何在 bash 中的 awk 命令中使用 bash 变量

如何在 bash 中的 awk 命令中使用 bash 变量

我想使用一组先前创建的变量来过滤名为 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_ivar_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

相关内容