如果 file1 的第一列与 file2 中的任何字符串匹配,则将其替换为 file1 的第二列

If the first column of file1 matches any string in file2, then replace it with the second column of file1

我有这个问题,但我还没有解决...我想操作这个文件..如果 file1 的第一列与 file2 中的任何字符串匹配,则将其替换为 file1 的第二列。 .. 然后折叠它(我的意思是,我只需要每个字段的唯一值或 output_file 第二列中的 "cell")..
哪种语言解决这个问题并不重要(awk,perl,python)...文件包含 100000 行或更多...我一直在尝试单行 awk 脚本,但没有...

感谢任何帮助。
此致

file1.txt

ID100000360640  ITEM1;ITEM2  
ID100000360638  ITEM1;ITEM3  
ID100000360644  ITEM1;ITEM4  
ID100000363115  ITEM5;ITEM2;ITEM3  
ID100000363116  ITEM1;ITEM7  
ID100000382126  ITEM8;ITEM1  
ID100000002165  ITEM1;ITEM2;ITEM3;ITEM9  
ID100000002596  ITEM1;ITEM10  
ID100000003084  ITEM1  

file2.txt

ID200000000419  ID100000360638;ID100000360640;ID100000360644;ID100000394921
ID200000000938 ID100000363115;ID100000363116;ID100000363117;ID100000382126  
ID200000001036  ID100000002165;ID100000398119 

output_expected.txt

ID200000000419  ITEM1;ITEM3;ITEM1;ITEM2;ITEM1;ITEM4;ID100000394921  
ID200000000938  ITEM5;ITEM2;ITEM3;ITEM1;ITEM7;ID100000363117;ITEM8;ITEM1;  
ID200000001036  ITEM1;ITEM2;ITEM3;ITEM9;ID100000398119  

processed_output.txt

ID200000000419  ITEM1;ITEM2;ITEM3;ITEM4;ID100000394921  
ID200000000938  ITEM1;ITEM2;ITEM3;ITEM5;ITEM7;ITEM8;ID100000363117;  
ID200000001036  ITEM1;ITEM2;ITEM3;ITEM9;ID100000398119 

谢谢

通过python3.

#!/usr/bin/python3
with open('file1.txt') as f, open('file2.txt') as r:
    d = {}
    m = f.read()
    for line in m.split('\n'):
        try:
            d.update(dict([tuple(line.split())]))
        except:
            pass
    j = r.read()
    for k in d:
        j = j.replace(k, d[k])
    print(j)    

输出:

ID200000000419  ITEM1;ITEM3;ITEM1;ITEM2;ITEM1;ITEM4;ID100000394921
ID200000000938 ITEM5;ITEM2;ITEM3;ITEM1;ITEM7;ID100000363117;ITEM8;ITEM1  
ID200000001036  ITEM1;ITEM2;ITEM3;ITEM9;ID100000398119 

这会产生折叠的输出:

$ awk 'FNR==NR{a[]=;next} {c="";delete d;delete e;split(, b, /;/);for (i in b)c=c";"(a[b[i]]?a[b[i]]:b[i]);split(substr(c,2),d,/;/); for(i in d)e[d[i]]=1; c=""; for (i in e){c=c";"i}; print ,substr(c,2)}' file1.txt file2.txt
ID200000000419 ID100000394921;ITEM1;ITEM2;ITEM3;ITEM4
ID200000000938 ITEM1;ITEM2;ITEM3;ID100000363117;ITEM5;ITEM7;ITEM8
ID200000001036 ITEM1;ITEM2;ITEM3;ID100000398119;ITEM9

工作原理

  • FNR==NR{a[]=;next}

    当我们读取第一个文件时,这会创建一个关联数组 a,它将第一个字段作为键与第二个字段关联作为值。因此,a[ID100000360640] 的值为 ITEM1;ITEM2。这是对 file1.txt 的所有行完成的。 next 语句导致跳过所有剩余的命令并跳转到下一行。

  • c="";delete d;delete e

    如果我们已经到了这里,那就意味着我们正在处理第二个文件,file2.txt。这三个命令为新行初始化变量 c 和数组 de

  • split(, b, /;/)

    这将用分号拆分第二个字段并将结果分配给数组 b

  • for (i in b)c=c";"(a[b[i]]?a[b[i]]:b[i])

    这将创建未压缩的输出。

  • split(substr(c,2),d,/;/); for(i in d)e[d[i]]=1

    这将创建一个关联数组 e,其键是未压缩输出中的每个字段。

  • c=""

    这会在我们向其添加压缩输出之前再次将 c 初始化为一个空行。

  • for (i in e)c=c";"i

    对于数组 e 中的每个键,我们将键添加到字符串 c。这将创建压缩输出。

  • print ,substr(c,2)

    这将打印完整的压缩行。

相当短的 awk 方式

awk 'FNR==NR{a[]=;next}
     {for(i in a)gsub(i,a[i])
      x=split(,b,";")
      for(i=1;i<=x;i++)y!~b[i]";"&&y=y?y";"b[i]:b[i];=y;y=""}1' file file2

输出

ID200000000419 ITEM1;ITEM3;ITEM2;ITEM4;ID100000394921
ID200000000938 ITEM5;ITEM2;ITEM3;ITEM1;ITEM7;ID100000363117;ITEM8
ID200000001036 ITEM1;ITEM2;ITEM3;ITEM9;ID100000398119

工作原理

FNR==NR{a[]=;next}

当文件记录号与总记录号匹配时(实际上意味着在读取第一个文件时)使用第一个字段作为键将第二个字段分配给一个数组。Next 意味着跳过所有进一步的指令并继续到下一条记录。

for(i in a)gsub(i,a[i])

现在我们在第二个文件中作为 FNR!=NR 了。
对于数组中的每个元素 gsub 将与键匹配的所有内容与数组中包含的内容进行交换。

x=split(,b,";")

将第二个字段拆分为数组 b,用 ; 分隔。
将数组的大小分配给 x.

for(i=1;i<=x;i++)

循环从 到数组的大小。

y!~b[i]";"&&  

如果变量 y 已经包含 b 中的拆分值则不要继续。

y=y?y";"b[i]:b[i] 

如果 y 存在,则将 b[i] 中的值添加到末尾,否则只需将 y 设置为 b[i]。

=y;y=""

将第二个字段设置为 y(我们的新字符串)中的值并将 y 重置为空。


资源

https://www.gnu.org/software/gawk/manual/html_node/String-Functions.html