I'm scripting the modification of a config file laid out like this:

auth = no
enabled = 0
username = 
password =
priority = 0
host = True

group = 
manual = False
enabled = 0
username = 

Where there are many [categories] and sometimes with the same key of a key/value pair.

Is it possible to craft a one-liner using awk/sed/grep/tr/cut/perl that can change the value of "enabled = 0" to "enabled = 1" but ONLY for the category [shovel]?


In sed you can use a range (stopping on the empty line at the end of the [shovel] category):

sed '/\[shovel\]/,/^$/ s/enabled = 0/enabled = 1/' file

the first part /\[shovel\]/,/^$/ means find a line with [shovel], keep going until you find an empty line, and do the following command(s) (in this case a simple s/old/new) only on that part of file

Note in response to comment: sed will not accept alternative delimiters in ranges and addresses (so escape any / characters that must be literal, if you need to match them), unless they are preceded by a backslash. You can always use an alternative delimiter in any following commands, for example:

sed '/\[shovel\]/,/^$/ s|enabled = 0|enabled = 1|' file


sed '\|\[shovel\]|, |^$| s|enabled = 0|enabled = 1|' file
  • Perfect. How would I change the delimiter? One of the values is a pathname so I'm trying to change the delimiter to a pipe. I've tried replacing all of the delimiters as well as just the two following the 's' and both error out. -sed -i "/\[shovel\]/,/^$/ s|home = .*|home = /home/test/" file gives me: sed: -e expression #1, char 48: unterminated 's' command and -sed -i "|\[shovel\]|,|^$| s|home = .*|home = /home/test/" file gives me: sed: -e expression #1, char 1: unknown command: '|' Jan 27 '17 at 17:01
  • You just need to put the last delimiter in: sed '/\[shovel\]/,/^$/ s|enabled = 0|enabled = 1|' @user1930831 :)
    – Zanna
    Jan 27 '17 at 18:50

Here's a solution using Perl, assuming your configuration is in config.ini:

perl -000 -n -i -e 's/^enabled = 0$/enabled = 1/m if /^\[shovel\]\n/; print;' config.ini

This does the following:

  • -000 - Read file in paragraph mode, essentially the same as doing $/ = "\n\n"; in the code.
  • -n - Run the specified code inside a while (<>) { } loop.
  • -i - In-line edit the specified file instead of printing to standard output. You can optionally specify an extension, which will cause the input file to be backed up with that extension. For instance, -i.bak would create a backup file called config.ini.bak.
  • -e - Executes the specified perl code.

The code itself says to replace lines containing exactly enabled = 0 with enabled = 1 if the input "paragraph" starts with [shovel] on a line by itself. The [ and ] have to be escaped since they normally have special meaning in a regular expression.

  • If you're using Perl, you could pick up the Config::IniFiles module and use that.
    – Kusalananda
    Jan 27 '17 at 8:01

can you try this awk solution

awk '/shovel/{flag=1}flag&&/enabled/{$NF=1;flag=0}1' input

You can restrict sed to only modifying a particular line:

 sed -i '3s/enabled = 0/enabled = 1/g' file

This will only modify the 3rd line for [purple]

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.