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

时间:2015-02-16 04:27:42

标签: python bash perl awk sed

我遇到了这个问题并且我还没有解决它...我想操纵这些文件..如果file1的第一列与file2中的任何字符串匹配,则将其替换为file1的第二列。 ..然后崩溃它(我的意思是,我只需要每个字段的唯一值或"单元格"在output_file的第二列中)..
解决这个问题的方法并不重要(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 

由于

3 个答案:

答案 0 :(得分:1)

通过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 

答案 1 :(得分:1)

这会产生折叠输出:

$ awk 'FNR==NR{a[$1]=$2;next} {c="";delete d;delete e;split($2, 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 $1,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[$1]=$2;next}

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

  • c="";delete d;delete e

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

  • split($2, 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 $1,substr(c,2)

    这将打印完整的压缩行。

答案 2 :(得分:1)

合理简短的awk方式

awk 'FNR==NR{a[$1]=$2;next}
     {for(i in a)gsub(i,a[i])
      x=split($2,b,";")
      for(i=1;i<=x;i++)y!~b[i]";"&&y=y?y";"b[i]:b[i];$2=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[$1]=$2;next}

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

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

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

x=split($2,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]。

$2=y;y=""

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


资源

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