2

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.
    – Stonecraft
    Aug 6, 2019 at 19:33
1

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!
    – Stonecraft
    Aug 6, 2019 at 19:34

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .