I know that both are used in PowerShell but for different contexts.
On the internet there is a paucity of information on this topic and the only site that talks about it (without making me understand the concept) is:
https://www.rlmueller.net/PowerShellEscape.htm
I am a beginner with PowerShell, I am recently approaching it.
A use case of the \
escape came up in the answer to this other topic of mine:
PowerShell removes multiple consecutive whitespaces when I pass arguments to a nested Start-Process command
Is there anyone who can explain to me in detail the difference between the escape backtick `
and backslash \
in PowerShell, with examples and use cases?
At least one source is welcome, but it is not mandatory.
CodePudding user response:
The backtick `
is used as the escape character in Powershell. That is, escaping quotes, tabs and whatnot. Unlike in many other environments, Powershell's newline is `n
, not \n
. This has the benefit of simplifying paths, since those use backslash in Windows.
As for a practical example, in many programming languages one needs to escape the backslashes in paths. If you have an application located at
c:\program files\newApplication\myApp.exe
Its path must be written as
c:\\program files\\newApplication\\myApp.exe
The double-backslash notation means that there is actaully a backslash, not a metacharacter such as tab or newline. Note that the path contains \newApplication
. Now, \n
usually means a newline, but it clearly isn't the case. The file does not reside in
c:\program files\
ewApplication\myApp.exe
after all, doesn't it?
The escaping is not needed in Powershell, as the backslash doesn't have special meaning by itself. When Powershell sees c:\program files\newApplication\myApp.exe
, it doesn't assign any special meaning to the forementioned \n
part, it is just a string literal.
The backslash \
is used as the escape character in regular expressions and to signify metacharacters. That is, to match a literal *
in regex, it must be escaped, lest it means the Kleene star (zero or more matches).
CodePudding user response:
vonPryz's helpful answer covers the PowerShell-internal angle well; let me attempt a systematic summary that includes the PowerShell CLI angle, as well as passing arguments with embedded "
to external programs:
Inside a PowerShell session, the only escape character is `
(the so-called backtick), in the following contexts:
Inside an expandable string (
"..."
, double quoted), but not inside a verbatim string ('...'
, single-quoted); for the supported escape sequences, see the conceptual about_Special_Characters help topic:# " must be escaped; escape sequence `n expands to a newline. "3`" of`nrain"
In unquoted command arguments:
# > must be escaped to write verbatim 'a>b', # since outside a quoted string an unescaped > is a redirection. Write-Output a`>b
For line-continuations:
# Spread the Get-Date call across two lines. # Important: ` must be the *very last char* on the line. Get-Date ` -Year 2525
Note: Various subsystems, whether PowerShell-specific or not, may have their own escaping rules, such as
\
in regular expressions and`
in wildcard expressions. Since arguments to those subsystems are delivered via PowerShell strings, it's best to use verbatim string literals, so as to avoid confusion between PowerShell's own string interpolation and what the target subsystem ends up seeing; e.g.'A $50 fine.' -match '\$50'
(\
is needed to treat regex metacharacter$
literally).
When PowerShell is called from the outside, via its CLI, different rules apply, possibly in addition:
In order to adhere to widely used convention for CLIs (command-line interfaces, programs that accept arguments via a command line) on Windows:
In calls to
powershell.exe
, the Windows PowerShell CLI,"
characters must be escaped with a backslash - i.e. as\"
- in order to be preserved during parsing of the original command line.pwsh.exe
, the CLI of the cross-platform, install-on-demand PowerShell (Core) 7 edition, now commendably alternatively accepts""
[1] in lieu of\"
, which makes calls fromcmd.exe
more robust.
By contrast, unescaped "
have syntactic function on the command line and tell PowerShell where the boundaries between arguments are; these "
instances are removed during command-line parsing.
This ensures that outside callers that merely want to invoke a PowerShell script file (.ps1
) with arguments, using the -File
parameter, can use the conventional syntax and needn't special-case calls to PowerShell's CLI.
However, if you pass a string containing PowerShell code to the CLI, using the -Command
parameter, what PowerShell ends up interpreting obviously must be syntactically valid PowerShell code.
Caveat: If you specify neither -Command
nor -File
:
powershell.exe
defaults to-Command
pwsh.exe
now defaults to-File
For the differences between -File
and -Command
calls and when to use which, see this answer.
If you use -Command
, there are two, sequential parsing stages:
The command-line parsing stage, where syntactic (unescaped)
"
are removed, and escaped\"
(or""
) turn into literal"
.The result of this stage is then parsed as PowerShell code, as it would be from inside a PowerShell session.
Therefore, you may situationally have to combine \
and `
-escaping; e.g. (call from cmd.exe
):
C:>powershell.exe -Command " \"3`\" of snow as of $(Get-Date)\" "
3" of snow as of 11/04/2021 14:13:41
Note the use of `\"
in order to make PowerShell see `"
, i.e. a properly escaped "
inside a "..."
string, after command-line parsing.
Escaping "
when calling external programs from PowerShell:
As a shell, it is PowerShell's job to pass the arguments that were passed based on its syntax rules to a target executable, so that the verbatim values that result from PowerShell's parsing are passed in a way that makes the target executable see them as such. In other words: PowerShell should perform any required escaping automatically, behind the scenes. (Unlike cmd.exe
, PowerShell cannot just pass its own argument syntax through as-is, because external CLIs cannot be expected to understand '...'
strings (single-quoting) or `
-escaping).
To use a simply example: Passing '3" of snow'
should be passed as "3\" of snow"
behind the scenes, based on the most widely used escaping convention.
Sadly, up to at least PowerShell 7.1, this is not the case, and embedded "
characters in arguments for external programs must additionally, manually be \
-escaped in order to be passed through properly.
# Broken behavior up to at least PS v7.1
PS> cmd /c echo '{ "foo": "bar" }'
"{ "foo": "bar" }" # !! Embedded " aren't escaped.
PS> choice.exe /d Y /t 0 /m '{ "foo": "bar" }'
{ foo: bar } [Y,N]?Y # !! When parsed by an executable,
# !! embedded " are effectively LOST.
# Manual escaping required.
PS> choice.exe /d Y /t 0 /m '{ \"foo\": \"bar\" }'
{ "foo": "bar" } [Y,N]?Y # OK
This bug has existed since v1, and has never been fixed so as to avoid breaking existing workarounds. This may change in the upcoming (as of this writing) v7.2 - whether the fix will require opt-in or not is not clear to me, and it also looks like high-profile exceptions for non-conformant Windows CLIs won't be accommodated.
See this answer for more information, which includes links to relevant GitHub issues.
[1] Inside PowerShell, in "..."
strings only, you may also use ""
to escape an embedded "
, as an alternative to `"