use sed to match on string but not remove anything past any number of specific characters then a character

Here is an example file called "config_file.txt":

setting01 = 0          # Comment for setting 01
setting02 = 1          # Comment for setting 02
setting03 = "./folder" # Comment for setting 03
setting04 = "string"   # Comment for setting 04
setting05 = 1          # Comment for setting 05

I need to replace each setting but not affect anything after the setting . This means do not remove any white space after setting, a "#", and anything after the "#".

I tried the following to replace "setting01"

sed -i "s/setting01\\ =\\ .*#/setting01\\ = 1/g" conf_file.txt

However that resulted in this:

setting01 = 1 Comment for setting 01
setting02 = 1          # Comment for setting 02
setting03 = "./folder" # Comment for setting 03
setting04 = "string"   # Comment for setting 04
setting05 = 1          # Comment for setting 05

When I want this:

setting01 = 1          # Comment for setting 01
setting02 = 1          # Comment for setting 02
setting03 = "./folder" # Comment for setting 03
setting04 = "string"   # Comment for setting 04
setting05 = 1          # Comment for setting 05

How can I accomplish this?


Solution 1:

You can use

sed -i -E 's/(setting01 = )("[^"]*"|[^[:space:]]+)/\11/g' conf_file.txt

Details:

  • -E - enable POSIX ERE regex syntax
  • (setting01 = ) - Group 1: setting01 =
  • ("[^"]*"|[^[:space:]]+) - Group 2:
    • "[^"]*" - a ", then zero or more chars other than " and then a "
    • | - or
    • [^[:space:]]+ - one or more non-whitespace chars

The \11 replaces the match with Group 1 value and 1 (as there can be no more than \9 backreferences in a POSIX regex, \11 is not parsed by sed as the 11th backreference).

See the online demo:

#!/bin/bash
s='setting01 = 0          # Comment for setting 01
setting02 = 1          # Comment for setting 02
setting03 = "./folder" # Comment for setting 03
setting04 = "string"   # Comment for setting 04
setting05 = 1          # Comment for setting 05'
 
sed -E 's/(setting01 = )("[^"]*"|[^[:space:]]+)/\11/g'  <<< "$s"

Output:

setting01 = 1          # Comment for setting 01
setting02 = 1          # Comment for setting 02
setting03 = "./folder" # Comment for setting 03
setting04 = "string"   # Comment for setting 04
setting05 = 1          # Comment for setting 05