Search code examples
sedshposix

Remove optional semicolon at line start with sed


I need to uncomment and edit this line using sed:

root@host:~# cat $CONF | grep "pm\.max_requests"
;pm.max_requests = 500

Tried this, but nothing worked:

root@host:~# sed -i "s/^;?pm\.max_requests *= *[^ ]*/pm.max_requests = 512/" ${CONF}
root@host:~# sed -i "s/^\;?pm\.max_requests *= *[^ ]*/pm.max_requests = 512/" ${CONF}
root@host:~# sed -i "s/^(;)?pm\.max_requests *= *[^ ]*/pm.max_requests = 512/" ${CONF}
root@host:~# sed -i "s/^(;?)pm\.max_requests *= *[^ ]*/pm.max_requests = 512/" ${CONF}

Here's what did work:

root@host:~# sed -i "s/^;pm\.max_requests *= *[^ ]*/pm.max_requests = 512/" ${CONF}

Problem is, the command has to work even if a semicolon isn't there.

I know I can start with something like below, but I was hoping I can have it done all in one line.

sed -i "s/#;pm\.max_requests/pm.max_requests/g" ${CONF}

Checked if this is a duplicate, but all I could find was Removed semicolon from a line in php.ini using shell command


Solution

  • sed by default uses the Basic Regular Expressions (BRE) regex flavour which does not parse ? as the "0 or 1" quantifier. Your commands fail as they try to match an inexistant literal ? character.

    Your alternatives are the following :

    • some implementations support \? as the "0 or 1" quantifier, although it's not POSIXly defined

      sed -i "s/^;\?pm\.max_requests *= *[^ ]*/pm.max_requests = 512/" ${CONF}
      
    • you can use the equivalent \{0,1\} quantifier

      sed -i "s/^;\{0,1\}pm\.max_requests *= *[^ ]*/pm.max_requests = 512/" ${CONF}
      
    • You could use the * quantifier instead of ?, which would lead to possibly removing multiple consecutive ; characters

      sed -i "s/^;*pm\.max_requests *= *[^ ]*/pm.max_requests = 512/" ${CONF}
      
    • you can switch to the Extended Regular Expressions (ERE) regex flavour, using sed -E for BSD sed or modern GNU sed and sed -r for older GNU sed. With this flavour, the ? quantifier will work as you expected it to.

      sed -iE "s/^;?pm\.max_requests *= *[^ ]*/pm.max_requests = 512/" ${CONF}