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.
CodePudding user response:
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 (in PowerShell, echo
- a built in alias of the Write-Output
cmdlet - isn't necessary and can be omitted):
# Note: Requires *GNU* sed
(echo '[where am I]' | sed 's/\[\([^09]\)/\x1b[94m[\x1b[0m\1/g')
Note the enclosing (...)
, which on Windows is required for Windows PowerShell to properly render the ANSI escape codes / VT (Virtual Terminal) sequences - see this answer.
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 ("..."
):
# Note: `e only works in PowerShell (Core) 7
# In Windows PowerShell, you'd have to 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 manually
\
-escape embedded"
chars., even inside verbatim (single-quoted) strings ('...'
) - see this answer.
CodePudding user response:
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.