【问题标题】:Match rows based on first field and combine second field根据第一个字段匹配行并组合第二个字段
【发布时间】:2011-11-28 23:16:10
【问题描述】:

我想使用 awk、sed 或类似方法将两个文件中第二个字段的条目合并。

文件0:

string:data:moredata

文件1:

string:random:moredata

如果 file0 中的第一个字段 stringfile1 中有匹配的条目,则打印

$random:$data

选择字段似乎很简单:

$ awk -F':' '{print $2}' filename

需要匹配行并打印匹配列$2

【问题讨论】:

    标签: shell sed awk


    【解决方案1】:

    这个怎么样 -

    awk -F":" 'NR==FNR {x[$1] = $0; y[$1] = $2; next} ($1 in x) {print $2":"y[$1]}' file1 file2
    

    执行:

    [jaypal~/Temp]$ cat file1
    string:data:moredata
    
    [jaypal~/Temp]$ cat file2
    string:random:moredata
    
    [jaypal~/Temp]$ awk -F":" 'NR==FNR {x[$1] = $0; y[$1] = $2; next} ($1 in x) {print $2":"y[$1]}' file1 file2
    random:data
    

    在这个解决方案中,我们将 file1 的整个记录​​加载到以列 1 为索引的数组中。我们在下一个文件中快速检查以查看列 1 是否存在。如果是,则执行 print 语句。

    否定测试:

    [jaypal~/Temp]$ cat file1
    string:data:moredata
    man:woman:child
    
    [jaypal~/Temp]$ cat file2
    man:random:moredata
    string:woman:child
    
    [jaypal~/Temp]$ awk -F":" 'NR==FNR {x[$1] = $0; y[$1] = $2; next} ($1 in x) {print $2":"y[$1]}' file1 file2
    random:woman
    woman:data
    

    只是为了补充说明,NR 和 FNR 是 awk 的内置变量。 NR 给出行号,并且在循环两个文件时不会重置为 0。相反,FNR 也是在第二个文件启动时重置为 0 的行号。因此,这允许我们将文件 1 存储到数组中,因为该操作仅在 NR==FNR 时执行。一旦这个条件变为假,就意味着第二个文件已经启动并且下一个模式动作语句开始执行。

    【讨论】:

      【解决方案2】:

      这个sed 解决方案可能适合您:

      # cat file1
      string0:data1:moredata
      string2:data3:moredata
      string4:data5:moredata
      string6:data7:moredata
      string8:data9:moredata
      # cat file2
      string0:random1:moredata
      string2:random3:moredata
      string4:random5:moredata
      cat file1 - <<<"EOF" file2 | 
      sed '1,/^EOF/{H;d};G;s/^\([^:]*:\)\([^:]*:\).*\1\([^:]*\).*/$\2$\3/p;d'
      $random1:$data1
      $random3:$data3
      $random5:$data5
      

      解释:

      使用EOF 分隔符连接文件。将第一个文件放入保存空间 (HS)。将 HS 附加到第二个文件中的所有行,以生成查找表。使用分组和反向引用来替换所需的输出结果。顺便说一句,$ 中的 $random:$data 是有意的吗?

      此解决方案还可以通过仅在查找和 file2 的每一行中保留必要的数据来提高效率。

      【讨论】:

      • 干得好!你应该开始写一本关于 SED 单行的电子书。我还没有弄清楚 G、H 和其他疯狂的东西。 :) +1
      • $ 不是必需的,想要传达不同的字段。感谢您的反馈。
      【解决方案3】:

      join - join lines of two files on a common field

      所以做你的 awk 事情,只打印数据和“关键”字段。然后执行类似于:join -1 1 -2 1 file1 file2 &gt; joined.dat

      的连接命令

      【讨论】:

      • 不确定如何仅使用 join 匹配行,因为它们可能无法排序,而且 file0 的行数可能更少。
      • 我不认为更少的行很重要。我假设它就像 db 表一样。 (我只使用过一次join,那是几年前的事了。)man 页面在排序上不清楚。一部分说你必须排序,另一部分暗示join 可以为你排序。我猜需要进行实验。
      猜你喜欢
      • 2020-03-28
      • 2018-03-25
      • 2017-11-16
      • 1970-01-01
      • 1970-01-01
      • 2014-08-04
      • 1970-01-01
      • 1970-01-01
      • 2012-12-21
      相关资源
      最近更新 更多