我在命令中的范围匹配中用“replaceString”替换第 N 行时遇到问题sed
,即是否可以相对替换范围匹配中的第 N 行?
考虑这个输入数据:
1 a
start
3 h
4 7
end
6 iii
7 4
并有这个命令:
sed '/start/,/end/ { *s/.*/replaceString/ }'
代替*
上面的命令,我该如何相对地说s/.*/replaceString/
在匹配范围的第二行执行命令?所以它会给我以下预期的输出。
1 a
start
replaceString
4 7
end
6 iii
7 4
这会将第二行绝对值更改为整个输入文件,这不是我想要的。
$ sed '/start/,/end/{ 2s/.*/replaceString/}' infile
1 a
replaceString
3 h
4 7
end
6 iii
7 4
请注意,我特别想这样做是sed
为了了解如何相对表示匹配范围的行号。的位置(行号)start
和end
模式未知。
答案1
使用 GNU,sed
您可以使用addr1,+N
地址范围作为计算内部行数的机器,如下所示:
sed '/start/,/end/{/start/,+1{/start/,+0!s/.*/replaceString/}}'
# -------------------------------------^ This is Nth - 2
# --------------------------^ This is Nth - 1
# So for instance to replace the 4th line after "start"
# (the 5th including "start") you would do:
sed '/start/,/end/{/start/,+4{/start/,+3!s/.*/replaceString/}}'
因此,基本上,经验法则是将您的*
“占位符地址”替换为以下表达式:
/<first-pattern>/,+<N-1>{/<first-pattern>/,+<N-2>!
# of course ended by one right brace after the series of
# commands to execute for the Nth inner line
POSIXly 另一种方法是使用保留空间作为累加器来记录行数,如以下sed
脚本:
#!/usr/bin/sed -f
# In practice we add a '-' to hold-space for each inner line
# until we have added as many '-' as the number of the
# wanted Nth inner line.
# Here is an example to replace the 4th line after
# "start" (the 5th including "start")
/start/,/end/{
x;/^-\{0,4\}$/{ # here the numbers within braces must be 0,N-1
s/^/-/;/-\{5\}/{ # here the number within braces must be N
x;s/.*/replaceString/;bdone
}
}
x
:done
<here do text-manipulation common to all lines of start/end blocks>
b # _skip_ clearing the accumulator kept in hold-space
}
# clear the accumulator that we kept in hold-space
x;s/.*//;x
不便之处在于,我们在计数期间保持占用空间,但至少我们消耗了行而不缓冲它们,因此它应该适用于任何大小的文件。
请注意,两者都只是一个快速的想法,因此可能还有改进的空间。
答案2
也许这样:
sed '/start/{:a;N;/end/!ba;s/[^\n]*/replaceString/2}' file