Home > Enterprise >  Using sed doesn't replace and there is no error too
Using sed doesn't replace and there is no error too

Time:08-30

I'm using Windows 10 x64, Powershell Core 7.2.6, and /usr/bin/sed (GNU sed) 4.8 installed with Git for Windows. No WSL at all.

I have a .env file like this.

ENDPOINT="localhost:3000"

and I need to change it to:

ENDPOINT=""

So I'm using this powershell command:

sed -i -e 's/ENDPOINT="localhost:3000"/ENDPOINT=""/g' .env

but it doesn't change the file and there is no error at all.

If I use this instead it works:

sed -i -e 's/ENDPOINT/THIS_WORKS/g' .env

Why?

Maybe the issues are the " double quotes?

I tried with `" and "" too. No luck!

I tried the suggestion to use:

sed -i -e 's/ENDPOINT=\"localhost:3000\"/ENDPOINT=\"\"/g' .env

but it errors with:

/usr/bin/sed: -e expression #1, char 67: unknown option to `s'

I also tried to reproduce the problem with:

'a', 'ENDPOINT="localhost:3000"', 'b' | sed -e 's/ENDPOINT=\"localhost:3000\"/ENDPOINT=\"\"/g'

The result is:

a                        
ENDPOINT="localhost:3000"
b                        

CodePudding user response:

  • To work around a long-standing PowerShell bug present up to at least 7.2.x, " chars. embedded in arguments passed to external programs must manually be escaped as \" - see this answer

    • The last two commands in your question do do that, which is normally enough, for most external CLIs.
  • Additionally, in your specific scenario you need to work around a quirk? bug? in the sed.exe implementation that ships with Git for Windows by ensuring that your -e argument (the sed script) contains at least one (insignificant) space (sic):

# Note the manually escaped " chars. (\") AND 
# the space right after the opening ' char.
# Result is now as expected: 'a', 'ENDPOINT=""', 'b'
'a', 'ENDPOINT="localhost:3000"', 'b' | 
  sed -e ' s/ENDPOINT=\"localhost:3000\"/ENDPOINT=\"\"/g'

The reason that the space makes a difference is that it causes PowerShell to enclose the argument in "..." behind the scenes when it builds the command line ultimately used for execution, which in the absence of spaces it does not do. Inexplicably, when the sed.exe implementation that comes with Git for Windows sees the unquoted token s/ENDPOINT=\"localhost:3000\"/ENDPOINT=\"\"/g on its command line, it doesn't recognize it correctly, even though it should (it should be equivalent to the double-quoted form, "s/ENDPOINT=\"localhost:3000\"/ENDPOINT=\"\"/g").

There are alternative workarounds:

  • Bypass the problem with " characters by using a sed escape sequence to represent them instead, namely \x22:

    'a', 'ENDPOINT="localhost:3000"', 'b' |
      sed -e 's/ENDPOINT=\x22localhost:3000\x22/ENDPOINT=\x22\x22/g'
    
  • Use --%, the stop-parsing token to explicitly control the quoting on the command line that sed.exe sees. Caveat: --% has significant limitations, notably the inability to (directly) incorporate PowerShell variables and expressions in the command - see this answer.

    # Note: Everything after --% is copied as-is to the command
    #       line used behind the scenes to invoke sed.exe
    'a', 'ENDPOINT="localhost:3000"', 'b' |
      sed -e --% "s/ENDPOINT=\"localhost:3000\"/ENDPOINT=\"\"/g"
    
  • Related