'Using backticks to escape characters in sed with PowerShell running on Windows
I'm aware that, in PowerShell, backticks(`) are used to escape characters instead of the backslash(\). Hence, when using sed, this:
echo '"where am I"' | sed "s/\"[^\"]*\"/\033[96m&\033[0m/g;"
will not work and I would have to write it like this:
echo '"where am I"' | sed "s/`"[^\`"]*`"/`e[96m&`e[0m/g;"
Hence, I would like to do the same with this code:
echo '[where am I]' | sed "s/\[\([^09]\)/\033[94m[\033[0m\1/g;"
The expected output should be:
However, when I tried to replace all the backslashes(\) with backticks(`), I can't seem to get the expected output as you can see below:
Any help would be appreciated. Thanks in advance.
Solution 1:[1]
As far as I'm aware, GNU sed doesn't support octal escape sequences - such as \033 to represent an ESC char. - only hexadecimal ones - such as \x1b.
The following command, which uses hex. escape sequences, should therefore work in both POSIX-compatible shells and in PowerShell:
# Note: Requires *GNU* sed
(echo '[where am I]' | sed 's/\[\([^09]\)/\x1b[94m[\x1b[0m\1/g')
In other words:
- Because the entire, verbatim string (
'...') is interpreted byseditself, there is no need for PowerShell's string interpolation (via"...").
Note:
The enclosing
(...), which on Windows is required for Windows PowerShell to properly render the ANSI escape codes / VT (Virtual Terminal) sequences in the terminal (console) - see this answer. It isn't needed if you capture the output in a variable or redirect it.In PowerShell, use of
echo- a built in alias of theWrite-Outputcmdlet - isn't necessary and can be omitted, due to PowerShell's implicit output behavior.
If your sed implementation doesn't support escape sequences such as \x1b - such as on macOS - you must indeed resort to using PowerShell's escape sequences inside an expandable (double-quoted) string ("..."); that is, you must replace \x1b with escape sequence `e in order to embed a verbatim ESC character into the string, up front (in Windows PowerShell, which doesn't support `e, use subexpression $([char] 0x1b) instead):
# Note: `e only works in PowerShell (Core) 7+
# In Windows PowerShell, use $([char] 0x1b)
(echo '[where am I]' | sed "s/\[\([^09]\)/`e[94m[`e[0m\1/g")
Important: The above commands contain no embedded " characters, which avoids a long-standing PowerShell bug that is still present as of PowerShell (Core) 7.2.2:
The need to unconditionally, manually
\-escape embedded"chars. in arguments passed to external programs - see this answer for details.A few quick examples that print verbatim
3" of snow:# Up to at least PowerShell 7.2.2: # Without escaping the embedded " with \ (too), # they would in effect be removed from the arguments. # Note that pipeline input is *not* affected. '3" of snow' | findstr '\"' # Windows /bin/echo '3\" of snow' # Unix # In expandable (double-quoted) strings, you therefore must escape *twice*: # once for PowerShell, then for the external-program call. '3" of snow' | findstr "\`"" # Windows /bin/echo "3\`" of snow" # Unix
Solution 2:[2]
You can pass non-interpolated expression strings to sed by using single quotes, '; e.g., 'a non-interpolated string'. instead of double quotes around the text. sed would take what it normally does for input. When you use double quotes, that's when powershell escaping comes into play.
Anyway, an alternative to sed would be leveraging the regular expression substitution built into powershell. For instance,
Write-Output ('[where am i]' -replace '\[(.*?)\]', "<<`e[5;36m`$1`e[0m>>")
Will capture the text between square brackets and place it between "chevrons" and make it blink.
Here's an article on inserting ANSI in text using powershell.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 |


