0

In a directory, I have too many site.ini.append.php (about 100 files).

They all look like:

[block1]
blabla[]
blabla[]=blabla
...
blabla[]=blabla

[block2]
blabla[]
blabla[]=blabla
...
blabla[]=blabla

[block3]
blabla[]
blabla[]=blabla
...
blabla[]=blabla

However, [block1] has different number of entries depending on the file. It's the same thing for the other blocks.

I need to add a new line at the end of [block2]:

[block2]
blabla[]
blabla[]=blabla
...
blabla[]=blabla
blabla[]=new_entry

And I cannot just use line number because, as I said, blocks have different entries, and [block2] may have 20 lines in a file, and 10 in another etc...

I was thinking about somthing like this

sed -n '/^\[block2\]$/,/^$/ a blabla[]=new_entry' path/to/one_of_the_site.ini.append.php

But it doesn't work, obviously, because /^\[block2\]$/,/^$/ is not an address.

How do I do it (preferably using sed)?

UPDATE

As explained here, /^[block2]$/,/^$/ is a valid address.

However, neither a, nor i fixes the issue for me

sed -n '/^\[block2\]$/,/^$/ a blabla[]=new_entry' path/to/one_of_the_site.ini.append.php 

sed -n '/^\[block2\]$/,/^$/ i blabla[]=new_entry' path/to/one_of_the_site.ini.append.php 

Environment

$ sed --version
GNU sed version 4.1.5
Copyright (C) 2003 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE,
to the extent permitted by law.
  • 1
    Your one liner works... /^\[block2\]$/,/^$/ is a valid address. It doesn't do what you want because it appends to all lines in that range. What you need here is to insert before the empty line in that range. Very simple. – don_crissti Jan 10 '18 at 14:56
  • @don_crissti the question is how do I insert before the empty line in that range? – smarber Jan 10 '18 at 15:03
2
 sed  '/block2/,/^$/s/^$/blabla[]=new_entry\n/g' filename

Above oneliner works fine .it matches the line between block2 and newline and then replaces newline with blabla[]=new_entry\n. Let me know for any issues

output

[block1]
blabla[]
blabla[]=blabla
...
blabla[]=blabla

[block2]
blabla[]
blabla[]=blabla
...
blabla[]=blabla
blabla[]=new_entry

[block3]
blabla[]
blabla[]=blabla
...
blabla[]=blabla
3

Following @don_crissti's suggestion, this seems to work in GNU sed and the BSD one on my Mac:

sed -e $'/^\\\[block2\\\]$/,/^$/ {/^$/i\\\nnew line\n}' < input

However, it does depend on the empty line being there, I'm not sure if your file has it if the block we're looking for is the last one.

We need sed to get an actual newline to start and terminate the i command, so I used the ANSI-C quoting $'' to make one (supported by ksh/zsh/bash). In a standard shell, you'll have to manually insert one.

  • I get an error :( sed: -e expression #1, char 0: unmatched {'` – smarber Jan 10 '18 at 15:15
  • @smarber, check the $ in front of the quote, we need it to give sed a hard newline. Otherwise it takes the final } as part of the line being inserted. – ilkkachu Jan 10 '18 at 15:21
  • @don_crissti, ah thanks. Bash leaves the backslash intact in $'\[' and I didn't seem to think it through. – ilkkachu Jan 10 '18 at 15:35
  • No problem. I recommend using the proper syntax (multiple expressions or separate lines) anytime i, a or c are used - less room for error and less confusing to newbs. – don_crissti Jan 10 '18 at 15:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.