sed 中匹配后的相对行号

sed 中匹配后的相对行号

我在命令中的范围匹配中用“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为了了解如何相对表示匹配范围的行号。的位置(行号)startend模式未知。

答案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

相关内容