cji*_*jcb 8 sed awk text-processing
比方说,我有这个包含 500 行文本的文件。
one
two
three
four
five
six
seven
eight
nine
ten
.
.
.
five-hundred
Run Code Online (Sandbox Code Playgroud)
如果我想用某个字符串替换匹配后的第五行,我会这样做:
sed '/two/{n;n;n;n;n;s/.*/MODIFIED/}' inputfile
Run Code Online (Sandbox Code Playgroud)
输出:
one
two
three
four
five
six
MODIFIED
eight
nine
ten
.
.
.
five-hundred
Run Code Online (Sandbox Code Playgroud)
但是如果我想在匹配后替换第 60 行呢?我不想写 'n' 次。
我尝试使用 x、h/H、g/G 和范围,但仍然无法获得所需的输出。
Fre*_*ddy 11
解决方法awk
:
awk '/two/{ n=NR+5 } NR==n{ sub(/.*/, "MODIFIED") }1' file
Run Code Online (Sandbox Code Playgroud)
或者如果你想更换线路
awk '/two/{ n=NR+5 } NR==n{ $0="MODIFIED" }1' file
Run Code Online (Sandbox Code Playgroud)
对于此类任务,您可能需要考虑如果在偏移之前再次出现搜索模式该怎么办。
awk -v offset=60 '
/two/ {x[NR + offset]}
NR in x {delete x[NR]; $0 = "MODIFIED"}
{print}'
Run Code Online (Sandbox Code Playgroud)
只要上面的 60 行包含two
.
/two/{
:loop
N
/\(\(.*\n\)\{5\}\).*/{
s//\1Modified/
b
}
b loop
}
Run Code Online (Sandbox Code Playgroud)
将其保存x.sed
并执行为
sed -f x.sed file
Run Code Online (Sandbox Code Playgroud)
或使用 GNU Sed 的 one-liner:
sed '/two/{:a;N;/\(\(.*\n\)\{5\}\).*/{s//\1Modified/;b;};ba;}' file
Run Code Online (Sandbox Code Playgroud)
逐行分析:
N
命令在模式空间中添加一行。\(.*\n\)\{5\}
——,把它放在一个捕获组中,不捕获最后一行 ( .*
) 并且
Modified
一行。loop
再一次。*一个空的正则表达式槽相当于之前使用的正则表达式,所以第 5 行相当于s/\(\(.*\n\)\{5\}\).*/\1Modified/
.
不太深奥的是使用 awk:
awk '{c--};/two/{c=5};c==0{$0="Modified"};{print}' file
Run Code Online (Sandbox Code Playgroud)
这从递减一个计数器开始c
,因为所有变量c
最初都是零,只有在找到匹配项时才会变为正值。
更明确的方法是
awk 'BEGIN{c=-1};/two/{c=5};c==0{$0="Modified"};{print};c>=0{c=c-1}' file
Run Code Online (Sandbox Code Playgroud)
有用的 Sed 资源:
一个sed
(但只有 GNU sed)没有循环和使用简单范围的解决方案是:
sed '/^two$/,+5{/^two$/,+4{b};s/.*/& hello/}'
Run Code Online (Sandbox Code Playgroud)
唯一需要调整的是匹配正则表达式以及 +5 和 +4 计数器。
比赛结束后的 100 行:
sed '/two/,+100{/two/,+99{b};s/.*/& Modified/}'
Run Code Online (Sandbox Code Playgroud)
也许这可以澄清它是如何工作的:
$ seq 10 | sed '/4/,+3{/4/,+2{s/.*/&changed/;b};s/.*/& Modified.../}'
1
2
3
4changed
5changed
6changed
7 Modified...
8
9
10
Run Code Online (Sandbox Code Playgroud)