3

I have a file sample.txt like this:

lots of text
lots of text


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

lots of text
lots of text

and I want to add some text "foobar" to get this:

lots of text
lots of text


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

lots of text
lots of text

I have looked at some related threads and tried a bunch of stuff but have not been able to join the information together in the correct way.

multiline matching: How can I use sed or ex to replace a block (multi-line code) with new block of text (code)? https://stackoverflow.com/questions/11234001/replace-multiple-lines-using-sed How can I use sed to replace a multi-line string?

appending: How to add a new line after the "test message1" using sed?

I've been trying stuff like this:

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


But so far I have not succeeded.

4 Answers 4

2

How about using a loop?

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

Explanation:

: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

At least in GNU sed, this can be written as a one-liner

sed -e '/^#nvram = \[/{:a; N; /\n#\]/!ba; a\foobar' -e '}' sample.txt
1
  • Thank you! Sorry about the slow response, I had some distractions. All of the answers worked for me but I'm crediting you because you were first. Commented Aug 6, 2019 at 19:33
2

With GNU sed for -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

You may need to tweak the regexp depending what you really mean by "anything" (e.g. can it contain a ]) and whether or not you have other similar blocks in your file.

This would be more robust, for example, if anything doesn't include ]s and you have other similar blocks in your input:

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

I'll pick one of the approaches you took and show you how to make it work, so that it resonates and also stays with you:

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

I personally don't like the above nd do somewhat differently:

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

Here's also a simple sed:

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

It finds a line in which the #nvram = [ has occurred and then all the lines after that and until the first occurence of an #] is addressed, then you substitute the #]\nfoobar for #].

1
  • In one line, cool! Thanks! Commented Aug 6, 2019 at 19:34

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.