我有一个简单的用例,我有一个像
这样的文件line_1
anything
anything
anything
aaa
line_2
line_3
anything
anything
anything
aaa
anything
anything
line_4
aaa
现在我必须替换line_3
之后的第一个aaa
。
输出——
line_1
anything
anything
anything
aaa
line_2
line_3
anything
anything
anything
YES REPLACE THIS
anything
anything
line_4
aaa
我可以用-
替换下一行的任何内容sed -i '/line_3/{n; s/aaa/YES REPLACE THIS/}' file.txt
但是aaa
不是下一行,我不知道它发生多少行之后,任何使用sed
,awk
或任何bash相关的解决方案都将工作,任何帮助将不胜感激。
使用awk
awk '/line_3/{f=1} f&&/aaa/{$0="YES REPLACE THIS";f=0} 1' file
一旦它看到line_3
设置一个标志,一旦它找到并替换模式就取消它
perl -wpe'if ($on) { $on = 0 if s/aaa/XXX/ }; $on = 1 if /^line_3$/' file
这只将结果行打印到屏幕上。如果您想要更改文件("in-place")添加-i
开关(perl -i -wpe'...'
),或者更好的-i.bak
也保留备份。
使用sed
$ sed '/line_3/,/line_4/{0,/^aaa/s/^aaa/YES REPLACE THIS/}' input_file
line_1
anything
anything
anything
aaa
line_2
line_3
anything
anything
anything
YES REPLACE THIS
anything
anything
line_4
aaa
这是建议的(由当前接受的答案):
perl -pe'$f = 1 if /^line_3$/; if ($f) { $f = 0 if s/^aaa$/YES REPLACE THIS/ };'
简化为:
perl -pe'$f ||= /^line_3$/; $f &&= !s/^aaa$/YES REPLACE THIS/;'
但是触发器运算符为我们做了很多工作!
perl -pe'/^line_3$/ .. s/^aaa$/YES REPLACE THIS/'
参见指定文件处理到Perl一行程序。
仅在perl
中使用替换,让file.txt
的内容为
line_1
anything
anything
anything
aaa
line_2
line_3
anything
anything
anything
aaa
anything
anything
line_4
aaa
然后
perl -p -0777 -e 's/(line_3.*?)aaan/$1YES REPLACE THISn/s' file.txt
给输出
line_1
anything
anything
anything
aaa
line_2
line_3
anything
anything
anything
YES REPLACE THIS
anything
anything
line_4
aaa
说明:-p
和-e
表示像sed
一样工作,-0777
表示将整个文件挤成一行。s/
-替换,/s
-使.
也匹配换行字符,我匹配line_3
和aaan
之前的非贪婪的任何字符,并替换所有我在aaan
之前匹配的由(
和)
表示的YES REPLACE THISn
。
ed
适合自动化ed下载文件:
ed -s file.txt <<<EOF
/line_3/;/aaa/,.c
YES REPLACE THIS
.
w
EOF
找到第一行匹配line_3
,然后c更改匹配aaa
之后的第一行,最后是w将修改后的文件返回。