I have a file that has indentation.
I want to replace a specific line but keep the indentation.
The file has a line such as

   \t\t     customerId = "123" // has indentation in the start of line

I am running this:

sed  -e 's:^\s*customerId = "'${OLD_ID}'": customerId = "'${NEW_ID}':' file

This does not do anything. Also I am aware that even if it worked I would mess up the indentation. How can I fix this?
Note: Solution doesn't have to be sed but I would like it to be able to be cross-platform

Tested @Gilles Quenot answer:

sed -E -i.bk "s:^(\s*)versionName = \"$OLD_ID\":\1versionName = \"$NEW_ID\":"   testfile   

Sample test:

    customerId = "1234"

Number was not replaced

  • Does anchoring the start of the pattern to zero or more whitespace characters really achieve anything? Can't you just do sed 's:customerId = "'${OLD_ID}'":customerId = "'${NEW_ID}'":' or sed '\:customerId: s:"'${OLD_ID}'":"'${NEW_ID}'":' ? – steeldriver Mar 28 '18 at 13:23

Using standard sed:

sed "s:^\([[:blank:]]*customerId = \)\"$OLDID\":\1\"$NEWID\":" file

The [:blank:] pattern will match a single space or tab character.

The sed expression captures everything on the line up to the ID itself, and replaces it with what was captured and the new ID.

Slightly nicer looking, possibly,

sed 's:^\([[:blank:]]*customerId = \)"'"$OLDID"'":\1"'"$NEWID"'":' file


$ cat file
    customerId = "1234"

$ OLDID=1234
$ NEWID=321

$ sed 's:^\([[:blank:]]*customerId = \)"'"$OLDID"'":\1"'"$NEWID"'":' file
    customerId = "321"

If the spaces around the = are optional, you may want to use

sed 's:^\([[:blank:]]*customerId *= *\)"'"$OLDID"'":\1"'"$NEWID"'":' file

Another approach suggested by don_crissti in comments:

sed '/customerId *=/s/"'"$OLDID"'"/"'"$NEWID"'"/' file

This has the benefit that it does not need a capture group. This looks for lines containing the word customerId followed by an equal sign and replaces the IDs on these rows.

  • So basically the problem was using the posix indicators? I thought -E would solve that but it does not – Jim Mar 28 '18 at 13:12
  • 1
    @Jim \s is not POSIX basic regular expression, nor a POSIX extended regular expression, but a PCRE ("Perl regular expression"). Some implementations of grep may support this with -P, but sed probably doesn't. – Kusalananda Mar 28 '18 at 13:14
  • 1
    \s and \S are very much supported by gnu sed since they are gnu regular expression extensions. On another note - if customerId can only appear in key = value pairs then simply replace ${OLD_ID} with ${NEW_ID} on lines that match customerId and that will preserve all spacing. – don_crissti Mar 28 '18 at 13:55
  • @don_crissti Thanks Don. I don't use the GNU tools too much, so I'm definitely not an authority on them. Thanks for the other suggestion too, I'll make an update soon. – Kusalananda Mar 28 '18 at 14:01
  • No problem, I know you're a BSD guy so I thought I'd leave a note about that (and a link). – don_crissti Mar 28 '18 at 14:07
sed -E "s:^(\s*)customerId = \"$OLD_ID\":\1customerId = \"$NEW_ID\":" file
  • Check my update in the post please – Jim Mar 28 '18 at 13:08

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.