Powershell: how escape many special chars as data, not operators?

81 views Asked by At

Got a problem understanding how to escape out chars in PS, so they are not interpreted as operators or instructions. I'm writing a PS script to find chars in filenames which are to be forbidden, and replace those chars for other chars (or remove). This includes typing the unwanted chars into the code:

$UnsupportedChars = '[!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ¡¢£¤¥¦§¨©ª«¬®¯]'

The first apostrophe (') above, indicates the start of the variable's content, and the apostrophe at the end of the variable indicates the end of the variable's content. Problem is that I also need to include the apostrophe inside the variable's contents as a 'not allowed char in filenames'. (see 7th char in var contents above)

This causes PS to interpret the (second) apostrophe as the end of the variable contents, as opposed to the third apostrophe which is standard. Surprisingly, using the grave-accent to escape doesn't work, PS won't accept it as valid code.

Same thing later in the code, in the loop which goes through-, finds- and exchange chars. I will need to include the quotation char (") as a 'not allowed chars in filename'. This presents the same kind of problem, which PS will not allow as valid code:

if ($_.Value -match """) { $newFileName = ($newFileName -replace """, "") }

Again, using the grave-accent to escape doesn't work, PS won't accept it as valid code:

if ($_.Value -match "`"") { $newFileName = ($newFileName -replace """, "") }

Problem seems to be how to declare all those special chars (see variable above) and separate them as data, as opposed to operators. Is there a way to encode this in PS, or will it be necessary to write a specific function to address this?

1

There are 1 answers

2
mklement0 On

The escaping requirements in PowerShell string literals are:

  • In verbatim, single-quoted strings, '...':

    • By design, all characters are used verbatim in such strings - no string interpolation is applied.

    • Purely for syntactic reasons, however, ' itself must be escaped, as '' - but see the next section about here-strings.

  • In expandable, i.e. interpolating, double-quoted strings, "...":

    • The following characters need escaping in order to be used verbatim:

      • ", for syntactic reasons - but see the next section about here-strings.
      • $, to avoid string interpolation (e.g. "$HOME", "$(1 + 2)")
      • `, to avoid interpretation as part of an escape sequence (e.g. "`t" to produce a tab char.)
    • They must be escaped with `, the so-called backtick, which is PowerShell's escape character; " may alternatively be escaped as ""

Examples:

# -> 6' tall
'6'' tall'

# -> 3" of snow
"3`" of snow" # or: "3"" of snow"

# -> You owe me $5.
"You owe me `$5."

# -> `t produces [  ]
"``t produces [`t]"

# -> '
''''

# -> "
"`"" # or: """"

Note that PowerShell string literals are also available in a multiline variant form called here-strings, which offer two benefits:

  • Conceptually clearer definition of multiline strings.
  • No need to escape embedded quote characters (but in the double-quoted (expandable) form, you still need to escape $ and `, as needed).

Examples:

# No need to escape ' (or ")
# -> 6' tall.
@'
6' tall.
'@

# No need to escape " (or '), but - if needed - $ and ` still do.
# -> 3" of snow. `t expands to [    ]
@"
3" of snow. ``t expands to [`t]
"@

As Keith Miller notes, a conceptually clear way of composing a string from a mix of verbatim and interpolated parts or expression results is to use -f, the format operator, which allows you to use a verbatim string as a template into which values are spliced based on placeholders such as {0}.

Examples:

# Same as: "``t produces [`t]"
# Avoids the need to escape ` in the template.
# {0} is a placeholder for the first RHS operand.
'`t produces [{0}]' -f "`t"

# Same as: "2 to the power of 5 is $([Math]::Pow(2, 5))"
# Avoids the need for $(...) enclosure.
'2 to the power of 5 is {0}' -f [Math]::Pow(2, 5)