Awk -控制我的$#变量扩展到合并两个具有可变列数的文件



我的bash脚本正在调用awk脚本,该脚本很好地合并了两个文件

mapfieldfile1=1
mapfieldfile2=2
awk  -v FS="t" 'BEGIN {OFS="t"}
                                FNR==NR{hash1['"$${mapfieldfile2}"']=$1 FS $3 FS $4 FS $5 FS $6;next}
                ('"$${mapfieldfile1}"' in hash1){ print $0, hash1['"$${mapfieldfile1}"']}' file2 file1

然而,我想要一个更通用的版本,我不需要硬编码我想要打印的列,我只想打印除id列之外的所有内容。将$1 FS $3 FS $4 FS $5 FS $6替换为$0"几乎"完成了工作,只是重复了id列。我一直在尝试动态创建一个类似于$1 FS $3 FS $4 FS $5 FS $6的字符串,但我在合并文件中字面上得到$1 $3 $4 $5 $6字符串,而不是扩展它们的值。此外,较小的副作用:我在中间添加了一个选项卡,并丢失了一些头,下面是代码和示例文件。我想找到我合并的解决方案,也了解我做错了什么,为什么我的变量没有扩大。

谢谢你的帮助!

mapfieldfile1=1
mapfieldfile2=2
awk  -v FS="t" 'BEGIN {OFS="t";strfields=""}
                        FNR==NR{for(i=1;i<=NF;i++) if(i!='"${mapfieldfile2}"') {strfields=strfields" "FS"  $"i};
                                hash1['"$${mapfieldfile2}"']=strfields;strfields="";next}
                        ('"$${mapfieldfile1}"' in hash1){print $0, hash1['"$${mapfieldfile1}"']}' file2 file1

$cat file1 
sampleid        s1      s2      s3      s4
1       1       1       1       1
2       2       2       2       2
3       3       3       3       3
4       4       4       4       4
$cat file2 
a0      sampleid        a1      a2      a3      a4
a0      1       a       a       a       a4
a0      2       b       b       b       a4
a0      3       c       c       c       a4
a0      5       e       e       e       a4
$cat first_code_result.txt (good one!)
sampleid        s1      s2      s3      s4      a0      a1      a2      a3      a4
1       1       1       1       1       a0      a       a       a       a4
2       2       2       2       2       a0      b       b       b       a4
3       3       3       3       3       a0      c       c       c       a4
$cat second_code_result.txt
sampleid        s1      s2      s3      s4                $1      $3      $4      $5      $6
1       1       1       1       1                 $1      $3      $4      $5      $6
2       2       2       2       2                 $1      $3      $4      $5      $6
3       3       3       3       3                 $1      $3      $4      $5      $6

试试这个(未测试):

awk -v mf1="$mapfieldfile1" -v mf2="$mapfieldfile2" '
BEGIN {FS=OFS="t"}
FNR==NR{sub(/t[^t]+/,""); hash1[$mf2]=$0; next}
($mf1 in hash1){ print $0, hash1[$mf1]}
' file2 file1

不要让shell变量在awk脚本中展开,使用regexp从记录中删除字段,并弄清楚为什么你没有向我们展示的脚本正在打印$3等,但你必须将它们包含在字符串中。你必须发布这个脚本来帮助调试它。

检查mf1 vs mf2应该出现的地方,我读你的脚本时感到困惑。

EDIT -我必须像上面那样调整它,我在使用它之前删除了$2:

$ awk -v mf1="1" -v mf2="2" '
BEGIN {FS=OFS="t"}
FNR==NR{key=$mf2; sub(/t[^t]+/,""); hash1[key]=$0; next}
($mf1 in hash1){ print $0, hash1[$mf1]}
' file2 file1
sampleid    s1  s2  s3  s4  a0  a1  a2  a3  a4
1   1   1   1   1   a0  a   a   a   a4
2   2   2   2   2   a0  b   b   b   a4
3   3   3   3   3   a0  c   c   c   a4

注意,上面的sub()依赖于键字段为$2,FS为选项卡。如果你需要一个更通用的解决方案,请告诉我们。

这里有一个版本,可以做你想要的任何关键字段值,并将在任何awk中工作,它只需要FS是一个选项卡或其他固定字符串(即不是regexp):

$ cat tst.awk
BEGIN { FS=OFS="t" }
NR==FNR {
    key = $mf2
    val = ""
    nf = 0
    for (i=1; i<=NF; i++) {
        if (i != mf2) {
            val = (nf++ ? val FS : "") $i
        }
    }
    hash1[key] = val
    next
}
$mf1 in hash1 { print $0, hash1[$mf1] }
$ awk -v mf1="1" -v mf2="2" -f tst.awk file2 file1
sampleid    s1  s2  s3  s4  a0  a1  a2  a3  a4
1   1   1   1   1   a0  a   a   a   a4
2   2   2   2   2   a0  b   b   b   a4
3   3   3   3   3   a0  c   c   c   a4

如果您的文件已经排序,则join的默认输出是您想要的

$ join -t$'t' -11 -22 file1 file2
sampleid        s1      s2      s3      s4      a0      a1      a2      a3     a4
1       1       1       1       1       a0      a       a       a       a4
2       2       2       2       2       a0      b       b       b       a4
3       3       3       3       3       a0      c       c       c       a4

或,用column修饰后

$ join -t$'t' -11 -22 file1 file2 | column -t
sampleid  s1  s2  s3  s4  a0  a1  a2  a3  a4
1         1   1   1   1   a0  a   a   a   a4
2         2   2   2   2   a0  b   b   b   a4
3         3   3   3   3   a0  c   c   c   a4

最新更新