複数行を一致させた後にいくつかのテキストを挿入するためにsedを使用する方法は?

複数行を一致させた後にいくつかのテキストを挿入するためにsedを使用する方法は?

sample.txt次のファイルがあります。

lots of text
lots of text


#nvram = [
#   these
#   could
#   be,
#   anything
#]

lots of text
lots of text

これを得るために「foobar」というテキストを追加したいと思います。

lots of text
lots of text


#nvram = [
#   these
#   could
#   be,
#   anything
#]
foobar

lots of text
lots of text

関連スレッドを見て多くのことを試しましたが、情報を正しい方法でリンクできませんでした。

複数行一致: sedまたはexを使用してブロック(複数行のコード)を新しいテキストブロック(コード)に置き換えるには? https://stackoverflow.com/questions/11234001/replace-multiple-lines-using-sed sedを使用して複数行の文字列を置き換える方法は?

追加: sedを使用して「test message1」の後に新しい行を追加するには?

私は次のことを試してきました。

sed  '/^#nvram = \[$/{
    N
    ^.*$
}/abc123/' sample.txt

sed '/^#nvram = \[$/ {N; s/\<^#nvram = \[$\>\n<^.*$\>/abc123/g}' sample.txt

sed '/^#nvram = \[$/ {N; s/\<#nvram = \[\>\n\<.*\>/abc123/g}' sample.txt

sed '/^#nvram = \[$/ {N; s/#nvram = \[\n.*/abc123/g}' sample.txt

sed '/^#nvram = \[$/ {N; /#nvram = \[\n.*/abc123/a}' sample.txt

sed '/^#nvram = \[$/ {N; /#nvram = \[(\n.*){1,}/abc123/a}' sample.txt


sed '/^#nvram = \[$/!b;n;cABC' sample.txt

sed '/^#nvram = \[$/N;cABC' sample.txt

sed '/^#nvram = \[$/N/#\]/a;cABC' sample.txt


sed '/^#nvram = \[$/,/#\]/{/^#nvram = \[$/n;/#\]/!{s/./abc/g}}' sample.txt

sed '/^#nvram = \[$/,/#\]/{/^#nvram = \[$/n;/#\]/!{/abc/a}}' sample.txt

sed '/^#nvram = \[$/,/#\]/{/^#nvram = \[$/n;/#\]/!/a abc}' sample.txt

sed '/^#nvram = \[$/,/#\]/{/^#nvram = \[$/n;/#\]/;/a abc}' sample.txt

sed '/^#nvram = \[$/,/#\]/{/^#nvram = \[$/n;/#\]/a abc}' sample.txt


しかし、これまで私は成功しませんでした。

答え1

ループを使うのはどうですか?

sed '/^#nvram = \[/{
:a                          
N                                                  
/\n#\]/!ba                                                                  
a\
foobar
}
' sample.txt

説明する:

:a              # begin loop
N               # append next line to pattern space
/\n#\]/!ba      # if we haven't matched the end marker yet, branch back to a
a\              # append after loop exits
foobar

少なくともGNU sedでは、1行のコードで書くことができます。

sed -e '/^#nvram = \[/{:a; N; /\n#\]/!ba; a\foobar' -e '}' sample.txt

答え2

GNU sedを使用すると、次のことができます-z

$ sed -z 's/#nvram = \[.*\]/&\nfoobar\n/' file
lots of text
lots of text


#nvram = [
#   these
#   could
#   be,
#   anything
#]
foobar

lots of text
lots of text

]「何でも」が実際に何を意味するのか(たとえば、含めることができるかどうか)と、ファイルに他の同様のブロックがあるかどうかに応じて、正規表現を調整する必要があるかもしれません。

anythingたとえば、sが含まれておらず、]入力に他の同様のブロックがある場合、これはより強力です。

sed -z 's/#nvram = \[[^]]*\]/&\nfoobar\n/' file

答え3

私はあなたが取るアプローチを選択し、それがあなたに共感して維持されるようにどのように機能させるかを示します。

$ sed -e '
   /^#nvram = \[$/,/^#]$/!b
   /^#]$/a\
Foobar
' sample.txt

私は個人的に上記のアプローチが好きではなく、他のタスクを実行します。

$ sed -e '
   /^#nvram = \[$/,/^#]$/!b
   /^#]$/G
   s/\n/&Foobar/
' sample.txt

答え4

これはまた簡単なsedです:

sed '/#nvram = \[/,/#]/ s/#]/#]\nfoobar/' file

この問題が発生した行を見つけて、anの最初の発生を解決する#nvram = [まで、その行の後のすべての行を見つけてから置き換えます。#]#]\nfoobar#]

関連情報