【问题标题】:AWK: select rows from shell variablesAWK:从 shell 变量中选择行
【发布时间】:2014-10-14 08:03:55
【问题描述】:

这里我有两个文件 data.txt 和 mrk.txt。

在第一行中,我想选择第二列中标有 2 的 id。第二行我只想保留以这些 id (3,5,8,9,10) 开头的行并删除其余行。有谁知道我该怎么做?

dam=$(awk '$2==2 {print $1}' data.txt)
./QmSim2uga.awk -v genotyped="$dam" mrk.txt > c_mark_001

QMSim2uga.awk 是

#!/bin/gawk -f
BEGIN{
nind=0
FIELDWIDTHS = "3 1 1 1 1 1"
}
($1 == dam){        
    nsnp=NF-1
    genotype=""
    for (i=1; i<=nsnp; i++){
        out=$(i+1)
        # QmSim -> UGA
        # 0 -> AA -> 0
        # 2 -> aa -> 2
        # 3 -> Aa -> 1
        # 4 -> aA -> 1
        # (missing does not exist) -> 5
        if(out>2) {out=1} 
        genotype=genotype out
    }
    if (NR % 10000 ==0){ printf("%s\n",NR) > "/dev/stderr" }
    printf("%10s%1s%" nsnp "s\n",$1," ",genotype)
    nind++
}
END{
printf("%s%10s%10s\n","nsnp, nanim",nsnp,NR) > "/dev/stderr"
}   

数据.txt

1  1
2  1
3  2
4  1
5  2
6  1
7  1
8  2
9  2
10 2

mrk.txt

1  02340
2  20433
3  43220
4  32344
5  02233
6  30423
7  24430
8  00223
9  03342
10 34402

所需的输出将是,mrk.txt 文件第 2 列中的“3”和“4”应替换为 1

3  11220
5  02211
8  00221
9  01112
10 11102

但是现在给出的代码,输出文件是空的

【问题讨论】:

  • 你当前和想要的输出是什么,你现在的代码有什么问题?
  • 想要的输出是 3 43220(/n) 5 02333(/n) 等等,现在输出文件是空的。我不知道这里出了什么问题。
  • 好的,我的问题已经回答了大约三分之一。
  • 你有修改代码的想法吗?

标签: shell variables awk subset


【解决方案1】:

针对新需求

旧要求

awk 'x[$1];{x[$1]=$2~2}' file file

新要求

awk 'a[$1]{gsub(/(3|4)/,"1",$2);print}{a[$1]=$2~2}' file file

【讨论】:

    【解决方案2】:
    join data.txt mrk.txt | awk '$2 == 2 { print $1, $3 }'
    

    【讨论】:

      【解决方案3】:

      试试下面的 awk 脚本:

      awk 'BEGIN {
          cnt=0
      }
      NR == FNR{
          if ($2 == 2)
             arr[cnt++] = $1
      }
      NR != FNR{
          for(i=0; i<cnt; i++)
              if(arr[i] == $1)
                 print $0
      }' data.txt mrk.txt
      

      NR==FNR代码块中,如果第二个字段值为2,我们将对应的$1存储在arr中。

      NR!=FNR 块(即mrk.txt)中,我们检查arr$1。如果匹配,则打印该行。

      【讨论】:

        【解决方案4】:

        一个更简单的awk 脚本可以实现你想要的。

        awk '$2==2{a[FNR]=$1} FNR!=NR && $1 in a{print $0}' data.txt mrk.txt 
        

        会产生

        3  43220
        5  02233
        8  00223
        9  03342
        10 34402
        

        它有什么作用?

        $2==2{a[FNR]=$1} 选择$2==2 所在的所有行并将$1 保存在数组a

        FNR!=NR 将选择第二个文件mrk.txt

        $1 in a 检查第 1 列,$1 是否在数组 a 中,如果是则打印整个记录 {print $0}

        编辑

        34 替换为1

        awk '$1 in a{gsub("[34]","1",$2); print $0};$2==2{a[FNR]}'
        

        会产生输出

        3 11220
        5 02211
        8 00221
        9 01112
        10 11102
        

        gsub("[34]","1",$2)

        将第二列$2中的每一个正则表达式[34]替换为1

        【讨论】:

        • 不需要print $0,如果参数后没有括号打开,awk 将打印它。
        • @Jidder 同意你的看法。谢谢你指出。只是为了清楚起见而添加。
        • 好的,你也不需要设置a[FNR]=$1。只需a[FNR]就足够了,因为你从来没有使用过里面的值。因为行号不能重复整个事情可以减少到'$1 in a;$2==2{a[FNR]}' data.txt mrk.txt
        • 非常感谢。实际上,我想将 mrk.txt 文件第二列中的元素的 3 和 4 更改为 1。我在编辑所需的输出文件时出错了。
        • @Jidder 更好。 a[FNR] 对我来说是一个新的想法。 :)
        猜你喜欢
        • 2014-01-04
        • 2013-01-08
        • 2014-01-20
        • 2015-08-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-01-02
        • 2020-03-28
        相关资源
        最近更新 更多