从一个文件中读取模式并使用 awk 和 gsub 执行字符串替换
read patterns from one file and perform string substitution using awk & gsub
我正在尝试使用 awk 和 gsub 进行一些大量的字符串替换,从文件(字典)中读取模式及其等价项并将它们替换为第二个文件 (input.txt)。
dictionary.txt:
c SUB1
u SUB2
我想把每一行存储在一个数组中,然后在第二个文件中搜索第一个字段(c
或u
)将其更改为SUB1
或SUB2
.我想更改整个字段,而不仅仅是出现的字符串。
我要修改的文件是input.txt
:
a ca mor
c cq nye
e c ult
d u cult
u as agc
x ul og
为了让事情更复杂一点,我只想在 file1
的第一列和第二列中应用替换(但仍然打印第三列)。
到目前为止我得到了这个:
awk 'NR==FNR{a[]=;next} {for (i in a) { gsub(i,a[i],)};{ gsub(i,a[i],)} }1' dictionary.txt input.txt
在第一个块中,我将 dictionary.txt
中的行存储在数组 a
中,使用 1 作为键,2 作为值(而 NR==FNR,而我正在读取第一个文件)。
然后,对于数组中的每个键,我使用 gsub(字段 $1 和 $2)对 input.txt
执行 2 次替换。
这是当前输出:
a SUB1a mor
SUB1 SUB1q nye
e SUB1 ult
d u cult
SUB2 as agc
x ul og
如您所见,我目前将 c
的所有实例替换为 SUB1
,即使它们是该字段的一部分(请注意第一行,第二个字段。我想避免这种情况。
此外,由于某种原因,第二个替换(u
到 SUB2
)在第一个字段中起作用(见第 5 行,第一个字段)但在第二个字段中不起作用(见第 4 和最后一行,第二场)。
这是我需要的输出:
a ca mor
SUB1 cq nye
e SUB1 ult
d SUB2 cult
SUB2 as agc
x ul og
你对我遗漏的东西有什么想法吗?
请注意,我试图避免基于 sed 的答案,因为我的真实数据在两个文件中都涉及很多行,而且会花费很长时间。非常感谢。
最佳,
对于全词匹配问题,您可以使用 ^
和 $
.
锚定您的正则表达式
第二个问题似乎只是上面评论中解决的额外大括号。
$ awk 'NR==FNR{a[]=;next} {for (i in a) {re="^"i"$"; sub(re,a[i],); sub(re,a[i],)}}1' dictionary.txt input.txt
a ca mor
SUB1 cq nye
e SUB1 ult
d SUB2 cult
SUB2 as agc
x ul og
当您要为整个字段寻找精确的字符串匹配时,我建议您这样做:
awk 'NR == FNR { a[] = ; next }
in a { = a[] } in a { = a[] } 1' dictionary.txt input.txt
这不是使用正则表达式,而是简单地进行字符串比较并在完全匹配的情况下进行替换。
感谢dave_thompson_085的建议。
我正在尝试使用 awk 和 gsub 进行一些大量的字符串替换,从文件(字典)中读取模式及其等价项并将它们替换为第二个文件 (input.txt)。
dictionary.txt:
c SUB1
u SUB2
我想把每一行存储在一个数组中,然后在第二个文件中搜索第一个字段(c
或u
)将其更改为SUB1
或SUB2
.我想更改整个字段,而不仅仅是出现的字符串。
我要修改的文件是input.txt
:
a ca mor
c cq nye
e c ult
d u cult
u as agc
x ul og
为了让事情更复杂一点,我只想在 file1
的第一列和第二列中应用替换(但仍然打印第三列)。
到目前为止我得到了这个:
awk 'NR==FNR{a[]=;next} {for (i in a) { gsub(i,a[i],)};{ gsub(i,a[i],)} }1' dictionary.txt input.txt
在第一个块中,我将 dictionary.txt
中的行存储在数组 a
中,使用 1 作为键,2 作为值(而 NR==FNR,而我正在读取第一个文件)。
然后,对于数组中的每个键,我使用 gsub(字段 $1 和 $2)对 input.txt
执行 2 次替换。
这是当前输出:
a SUB1a mor
SUB1 SUB1q nye
e SUB1 ult
d u cult
SUB2 as agc
x ul og
如您所见,我目前将 c
的所有实例替换为 SUB1
,即使它们是该字段的一部分(请注意第一行,第二个字段。我想避免这种情况。
此外,由于某种原因,第二个替换(u
到 SUB2
)在第一个字段中起作用(见第 5 行,第一个字段)但在第二个字段中不起作用(见第 4 和最后一行,第二场)。
这是我需要的输出:
a ca mor
SUB1 cq nye
e SUB1 ult
d SUB2 cult
SUB2 as agc
x ul og
你对我遗漏的东西有什么想法吗?
请注意,我试图避免基于 sed 的答案,因为我的真实数据在两个文件中都涉及很多行,而且会花费很长时间。非常感谢。
最佳,
对于全词匹配问题,您可以使用 ^
和 $
.
第二个问题似乎只是上面评论中解决的额外大括号。
$ awk 'NR==FNR{a[]=;next} {for (i in a) {re="^"i"$"; sub(re,a[i],); sub(re,a[i],)}}1' dictionary.txt input.txt
a ca mor
SUB1 cq nye
e SUB1 ult
d SUB2 cult
SUB2 as agc
x ul og
当您要为整个字段寻找精确的字符串匹配时,我建议您这样做:
awk 'NR == FNR { a[] = ; next }
in a { = a[] } in a { = a[] } 1' dictionary.txt input.txt
这不是使用正则表达式,而是简单地进行字符串比较并在完全匹配的情况下进行替换。
感谢dave_thompson_085的建议。