I try to use sed to insert a line after [Block B] in the following file:
[Block A]
line 1
line 2
[Block B]
line 1
line 2
[Block C]
line 1
line 2
The command I used:
sed '/\[Block B\]/,/^$/a\inserted line' file
The correct/desired result should be:
[Block B]
line 1
line 2
inserted line
However, I got this instead:
[Block B]
inserted line
line 1
inserted line
line 2
inserted line
Please tell me how I can get the desired result using sed. Thanks!
sed -e '/\[Block B\]/{:a;n;/^$/!ba;i\inserted line' -e '}'
I found this question while looking for a solution to my own problem, which was similar but a little different. I adapted the answers here to solve my problem.
I needed to insert some text at the end of a block inside a configuration file like this:
name1 {
...
}
name2 {
...
inserted text line 1
inserted text line 2
}
name3 {
....
}
To achieve this I took @toyntz comment from above and adapted it thus:
/^name2 {/,/^}/{
/^}/i\ inserted text line 1
/^}/i\ inserted text line 2
}
That is just the sed expression; it can be put in a file and executed with sed -f
like this:
$ sed -f sed_expression data_file
This first expression searches for a range of lines starting with name2 {
occurring at the beginning of a line and ending with }
also occurring at the beginning of a line. That selects the block to work on. The remaining expression is enclosed in {
curly braces}
and operates on the selected range. It contains one command per line we wish to insert, each with an expression /^}/
that matches the line with the closing curly brace followed by an insert i
operation to insert a line of text. The i
is followed with a \
so that leading whitespace is also inserted.
I then took the expression a bit further, replacing the two insert commands with one:
/^name2 {/,/^}/{
/^}/i\
inserted text line 1\
inserted text line 2
}
Here the text to be inserted by one command is spread across the following two lines. Note the additional trailing \
on the first line to continue the single command.
Next, I reduced it to one line. It makes it messy and harder to read but it still works:
/^name2 {/,/^}/{/^}/i\ inserted text line 1\n inserted text line 2
}
The two lines to be inserted are separated by a newline \n
. Astute readers will note that there are actually two lines there - you can't put the closing brace on the end of the first line; this is why the other answers above have a second -e expression. So, the above was the best I could do. To represent that on a bash command line:
sed -e '/^name2 {/,/^}/{/^}/i\ inserted text line 1\n inserted text line 2' -e '}' data_file
I've written out this longhand in the hope that it explains to anyone looking to insert at the end of a block of text how a sed expression can be written to achieve that. Sed expressions can be quite cryptic and difficult to figure out - hopefully my explanations help in that regard.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With