【问题标题】:read patterns from one file and perform string substitution using awk & gsub从一个文件中读取模式并使用 awk 和 gsub 执行字符串替换
【发布时间】:2016-02-04 11:20:04
【问题描述】:

我正在尝试使用 awk 和 gsub 进行一些大规模的字符串替换,从文件(字典)中读取模式及其等效项并将它们替换为第二个文件(input.txt)。

dictionary.txt:

c SUB1
u SUB2

我想将每一行存储在一个数组中,并在第二个文件中搜索第一个字段(cu)以将其更改为SUB1SUB2。我想更改整个字段,而不仅仅是字符串。

我要修改的文件是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[$1]=$2;next} {for (i in a) { gsub(i,a[i],$1)};{ gsub(i,a[i],$2)} }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,即使它们是该字段的一部分(请注意第一行,第二个字段。我想避免这种情况。

另外,由于某种原因,第二个替换(uSUB2)在第一个字段(参见第 5 行,第一个字段)中有效,但在第二个字段中无效(参见第 4 行和最后一行,第 2 个字段) .

这是我需要的输出:

a ca mor
SUB1 cq nye
e SUB1 ult
d SUB2 cult
SUB2 as agc
x ul og

你对我缺少什么有什么想法吗?

请注意,我试图避免基于 sed 的答案,因为我的真实数据在两个文件中都涉及很多行,而且会花费很长时间。非常感谢。

最好的,

【问题讨论】:

  • for (i in a) { gsub(i,a[i],$1)};{ gsub(i,a[i],$2)} 中,只有第一个gsub 包含在for 循环中。这是你的意图吗?
  • 不,这是一个错误。当我将其更改为{for (i in a) { gsub(i,a[i],$1);gsub(i,a[i],$2)} } 时,字典中第二行的问题就解决了。感谢您的关注。

标签: arrays awk gsub gawk


【解决方案1】:

当您正在寻找与整个字段完全匹配的字符串时,我建议您这样做:

awk 'NR == FNR { a[$1] = $2; next } 
     $1 in a { $1 = a[$1] } $2 in a { $2 = a[$2] } 1' dictionary.txt input.txt

这不是使用正则表达式,而是简单地进行字符串比较并在完全匹配的情况下进行替换。

感谢dave_thompson_085 的建议。

【讨论】:

  • 你可以用$1 in a {$1=a[$1]} $2 in a {$2=a[$2]} 1简化一些语法
  • 这个也不错!
  • @dave_thompson_085 你说得对,这样好多了。编辑以使用您的建议。
【解决方案2】:

对于全词匹配问题,您可以使用^$ 锚定您的正则表达式。

第二个问题似乎只是上面 cmets 中解决的额外大括号。

$ awk 'NR==FNR{a[$1]=$2;next} {for (i in a) {re="^"i"$"; sub(re,a[i],$1); sub(re,a[i],$2)}}1' dictionary.txt input.txt
a ca mor
SUB1 cq nye
e SUB1 ult
d SUB2 cult
SUB2 as agc
x ul og

【讨论】:

  • 完美,谢谢!我不知道 "^" 和 "$" 语法可以用来分隔字段,我认为它只适用于行。
猜你喜欢
  • 2021-11-16
  • 1970-01-01
  • 2017-05-20
  • 1970-01-01
  • 1970-01-01
  • 2021-01-29
  • 2018-10-19
  • 1970-01-01
  • 2022-06-10
相关资源
最近更新 更多