sed で一致後の相対行番号

sed で一致後の相対行番号

コマンドの範囲一致で、N行目を「replaceString」に置き換えるのに問題がありますsed。つまり、範囲一致でN行目を比較的変更できますか

次の入力データを考慮してください。

1 a
start
3 h
4 7
end
6 iii
7  4

次のコマンドを使用してください。

sed '/start/,/end/ { *s/.*/replaceString/ }'

上記のコマンドの代わりに*比較的一致s/.*/replaceString/する範囲の2行目コマンドを実行するにはどうすればよいですか?だからそれは私に次の予想結果を与えるでしょう。

1 a
start
replaceString
4 7
end
6 iii
7  4

これにより、2行目の絶対値が入力ファイル全体に変わりますが、これは私が望むものではありません。

$ 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もう1つのアプローチは、次のスクリプトのように予約済みスペースをアキュムレータとして使用して行数を記録することです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

不便な点は、カウント中に空間を占有し続けることです。ただし、少なくともバッファリングなしで行を消費するため、すべてのサイズのファイルに対して機能する必要があります。

どちらも簡単なアイデアなので、改善の余地があるかもしれません。

おすすめ記事