打印具有多个定界符的相似列的行

print lines that have similar columns with multiple delimiters

我有两个文件:

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[]; next};  in a' file1.txt file2.txt

你可以这样做:

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

我的方法是从file1中提取你想要的"key"值。

awk -F_ '
        NR==FNR{str="^""_""_"; arr[str]=str}
        NR!=FNR{for (x in arr){if ([=10=] ~ x) {print  [=10=] ; 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

这会将文件 1 的前 3 个 _ 分隔值重建为 "_""_"。 删除 # 注释字符以查看 arr[] 中存储的值。

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

IHTH

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

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

dn_id101_400_XX_XX diffstring1
dn_id111_60_GG_CC diffstring3

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

您只需要:

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