【问题标题】:print lines that have similar columns with multiple delimiters打印具有多个分隔符的相似列的行
【发布时间】:2016-03-08 12:30:14
【问题描述】:

我有两个文件:

file1.txt

dn_id101_400_CT_TC    string1
dn_id111_60_TT_AA    string2

file2.txt

dn_id101_400_XX_XX    diffstring1
dn_id400_40_XY_YX    diffstring2
dn_id111_60_GG_CC    diffstring3

如果 file1.txt 中由_ 分隔的前三个元素存在于 file2.txt 的行中,我想打印 file2.txt 中的行。这是我想要的输出:

dn_id101_400_XX_XX    diffstring1
dn_id111_60_GG_CC    diffstring3

有没有办法做到这一点?也许通过更改awk 的分隔符?我不确定如何在 awk 命令中处理多个分隔符。这是我想使用的示例:

awk -F"\t" 'FNR==NR {a[$1]; next}; $1 in a' file1.txt file2.txt

【问题讨论】:

    标签: awk text-processing


    【解决方案1】:

    具有cutpastejoinsort 和函数定义的替代解决方案以复制 awk 功能

    $ f() { paste <(cut -d_ -f1-3 ${1}) ${1} | sort; }; \
      join -o2.2,2.3 <(f file1) <(f file2)    
    
    dn_id101_400_XX_XX diffstring1
    dn_id111_60_GG_CC diffstring3
    

    创建连接的键和排序,选择列输出,定义函数用于消除重复代码。

    【讨论】:

    • 这可能会很好。但是,我在让我的join 正常工作方面遇到了一些严重的问题。谢谢你的建议! :)
    • 什么不起作用?除了输出格式,join 中没有隐藏的魔法,使用默认键。
    【解决方案2】:

    你只需要:

    $ awk -F_ '{k=$1 FS $2 FS $3} NR==FNR{a[k];next} k in a' file1 file2
    dn_id101_400_XX_XX    diffstring1
    dn_id111_60_GG_CC    diffstring3
    

    【讨论】:

      【解决方案3】:

      你可以这样做:

      $ awk -F"\t" '     
                  {s=$1; sub(/_[[:upper:]]+_[[:upper:]]+$/, "", s)} 
          FNR==NR { arr[s]++} 
          FNR<NR && (s in arr)' f1 f2
      dn_id101_400_XX_XX  diffstring1
      dn_id111_60_GG_CC   diffstring3
      

      假设/_[[:upper:]]+_[[:upper:]]+$/ 正确描述了您需要删除以使两个文件之间的数据键重叠的部分。

      如果你想从左到右(不管_在前三个之后的数量),请改用split

      $ awk -F"\t" '     
                  { split($1, a, /_/); s=a[1]"_"a[2]"_"a[3]} 
          FNR==NR { arr[s]++} 
          FNR<NR && (s in arr)' f1 f2
      

      【讨论】:

      • 谢谢@dawg!我能够轻松地编辑第二个解决方案以适应我的具体情况。
      【解决方案4】:

      我的方法是从 file1 中提取您想要的“关键”值。

      awk -F_ '
              NR==FNR{str="^"$1"_"$2"_"$3; arr[str]=str}
              NR!=FNR{for (x in arr){if ($0 ~ x) {print  $0 ; next }}}
              #END{for(x in arr) print "arr["x"]="arr[x]}
              ' f1.txt f2.txt
      

      输出

      dn_id101_400_XX_XX    diffstring1
      dn_id111_60_GG_CC    diffstring3
      

      这会将来自 file1 的前 3 个 _ 分离值重构为 $1"_"$2"_"$3。 删除# 注释字符以查看arr[] 中存储了哪些值。

      NR==FNRNR!=FNR 控制将哪个文件读入arr[] 以及处理哪个文件以匹配($0 ~ str)

      IHTH

      【讨论】:

      • 您可能希望将正则表达式匹配锚定到字符串的开头,并在速度成为问题时跳出循环。
      • @shawnt00 :是的,感谢您的好主意。更新了我的答案,尽管 EdM 在减少字符数方面击败了我! ;-) 祝大家好运。
      猜你喜欢
      • 2013-05-23
      • 1970-01-01
      • 2022-01-17
      • 2020-11-05
      • 2018-09-22
      • 1970-01-01
      • 2022-01-18
      • 2022-12-16
      • 1970-01-01
      相关资源
      最近更新 更多