【问题标题】:awk hash applying conditions on two input filesawk 哈希对两个输入文件应用条件
【发布时间】:2021-10-30 09:10:58
【问题描述】:

我正在尝试使用awk 比较两个文件,我想根据三个条件将它们组合起来。

  1. 第 2 列等于第 1 列
  2. 第 3 列大于或等于第 2 列
  3. 第 3 列小于或等于第 3 列

文件如下所示:

文件1

snp1 14 6371334
snp2 14 7928189
snp3 14 31819743
snp4 14 62133529
snp5 14 62616434
snp6 14 17544926
snp7 14 31639444

文件2

14 71159186 72228540 31
14 15732809 16677121 68
14 45003977 46299534 69
14 61965465 64286878 128
14 17378950 17833828 141
14 12877549 13217565 193
14 31369019 31785149 194
14 49883707 49905143 197

期望的输出是:

snp1 14 6371334 0 
snp2 14 7928189 0
snp3 14 31819743 0
snp4 14 62133529 128
snp5 14 62616434 128
snp6 14 17544926 141
snp7 14 31639444 194

我试过了:

awk 'NR==FNR {a[$1]=$1;b[$2]=$2;c[$3]=$3;d[$4]=$4;next} {if($2 in a && $3 >= b[$2] && $3 <= c[$3]) print $1,$2,$3,d[$4]}' file2 file1

但它不是那样工作的。

有什么帮助吗?

谢谢!

【问题讨论】:

    标签: unix awk


    【解决方案1】:

    看起来您可能想为 snp 分配一个间隔
    也就是说,如果一个 snp 在某个时间间隔内
    报告与区间关联的标识符。

    我几乎不喜欢看到的事情包括使用NR==FNR 模式 没有对应的NR!=FNR 模式。

    四个独立数组的想法,其中每个键都是其值的副本
    ......你能用它做什么?
    同一行中的任何项目都不会与其他保存偶然相关。

    并不是说你应该这样做......
    但是您可能认为最好使用以下构造:

    a[NR]=$1;b[NR]=$2 ....
    

    在同一行相关的项目可以恢复

    第一个块中的尾随 ;next 可能无济于事
    因为 awk 的自然行为是在不被告知的情况下继续进行。

    第二块还没有接受 awk 的精髓...
    条件在块之前的隐式 if 中

    类似

    NR != FNR && $1 in a   ... {print ...
    

    如果可能,您通常希望先使用小得多的文件 然后流过第二个,尤其是当第二个更大时。

    注意:您的样本似乎具有未被利用的顺序

    轮廓可能看起来像

    read file1 into array(s) maintaining order
    
    process first item from file1 through file2 until  
     found OR not exists is determined.
    
    proceed to process next item from file1 (continuing from where you are in file2)
    rinse & repeat
    

    我可以为你做你的工作,但你会得到更好的服务 考虑到一些
    提出的观点 如果您再次卡住,请发布更接近的近似值 一些可能有效的东西,我会回来查看。

    【讨论】:

    • 非常感谢您分享所有这些知识。我还在学习awk,但是你可以用它做很多事情真是令人惊讶。我或多或少地解决了这个问题。 join -1 2 -2 1 &lt;(sort -bk2,2 file1) &lt;(sort -bk1,1 file2) | awk '$3&gt;=$4 &amp;&amp; $3&lt;=$5 {print $2,$1,$3,$6}' &gt; out我肯定需要多学习awk。有什么建议可以在哪里了解更多信息(书籍、网页等)?
    • 要学习 awk,请阅读 Arnold Robbins 所著的《Effective AWK Programming, 5th Edition》一书。
    【解决方案2】:

    对于数组的数组,使用 GNU awk 并假设一个值只能在给定键的 1 个范围内:

    $ cat tst.awk
    NR==FNR {
        ranges2vals[$1][$2 FS $3] = $4
        next
    }
    { val = 0 }
    $2 in ranges2vals {
        for (range in ranges2vals[$2]) {
            split(range,r)
            if ( (r[1] <= $3) && ($3 <= r[2]) ) {
                val = ranges2vals[$2][range]
                break
            }
        }
    }
    { print $0, val }
    

    $ awk -f tst.awk file2 file1
    snp1 14 6371334 0
    snp2 14 7928189 0
    snp3 14 31819743 0
    snp4 14 62133529 128
    snp5 14 62616434 128
    snp6 14 17544926 141
    snp7 14 31639444 194
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-18
      • 2017-10-28
      • 1970-01-01
      • 2023-04-07
      • 2023-03-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多