首页 > 解决方案 > linux在行号之后匹配模式直到结束并替换一次

问题描述

要求是这样的:

输入文件:

.......
.......
foo ......
.......
.......
foo ......
.......
.......
foo ......
.......
.......

输出文件:

.......
.......
foo bar
.......
.......
foo nobar
.......
.......
foo barno
.......
.......

我已经想到了逻辑并找到了实现上述内容的部分。逻辑就是这样。

  1. 最初lineno=0
  2. 匹配模式从lineno文件末尾开始。找到模式后,获取行号 ,lineno=<matched line number> + 1仅用第一个值替换一次。
  3. 用第二个值重复第二步。
  4. 用第三个值重复第二步。

我只发现,如何获取匹配模式的行号,如何只替换一次。但是对于第一部分“从文件的特定行号开始匹配”,我什么也没得到。

上述要求可以在linux中实现吗?

提到的逻辑更可取,因为它可以在循环中处理。也欢迎其他想法/即兴创作。

编辑1:

在所有评论之后,这是我的第一次尝试:

x=($(awk '/foo/ {print NR}' foo_test))    #foo_test contains the above input
sed -i "${x[0]}s/.*/foo bar/" foo_test
sed -i "${x[1]}s/.*/foo nobar/" foo_test
sed -i "${x[2]}s/.*/foo barno/" foo_test

还有其他更好的解决方案吗?

标签: linuxunixawksed

解决方案


这是一个示例 awk 脚本,用于一次扫描完成任务。

输入文件input.txt

line 1
foo line 2
foo line 3
line 4
foo line 5
foo line 6
line 7
line 8
foo line 9
foo line 10
line 11
foo line 12

awk 脚本script.awk

/^foo / {               # for each input line starting with foo
    fooCount++;         # increment foo coutner
    if (fooCount%3 == 1) $1 = $1" bar";   # First match. Add bar to 1st field
    if (fooCount%3 == 2) $1 = $1" nobar"; # Second match. Add nobar to 1stfield
    if (fooCount%3 == 0) $1 = $1" barno"; # Third match. Add barno to 1st field
}
1                       # print current line

运行命令:

awk -f script.awk input.txt

输出:

line 1
foo bar line 2
foo nobar line 3
line 4
foo barno line 5
foo bar line 6
line 7
line 8
foo nobar line 9
foo barno line 10
line 11
foo bar line 12

请评论


推荐阅读