如果 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
和数组 d
和 e
。
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
我有这个问题,但我还没有解决...我想操作这个文件..如果 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
和数组d
和e
。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