Reputation: 1083
Why doesn't this work?
$drvrInstFilePath = "$sharePath\$imageName\ISO`$OEM$`$1\RPKTools\RPKDriverInst.bat"
echo $drvrInstFilePath
$drvrInstContent = Get-Content -LiteralPath "$sharePath\$imageName\ISO`$OEM$`$1\RPKTools\RPKDriverInst.bat" | Out-String
The echo shows the right path, but the Get-Content command expands the $oem and $1 to blank strings, even though they are escaped. Why?
Upvotes: 85
Views: 101923
Reputation: 2414
You used double quotes with simple backtick. This is an incorrect combination for the type of call used. Your successful options to escape the dollar sign ($) in this type of PowerShell call are:
Note the exceptions at the end about function call parameters.
For those unfamiliar with the distinction, it is important not to confuse the backtick character (`) with the single-quotation character (') in these escapes.
Examples:
[SUCCESS] Double quotes as container with backslash-backtick as escape:
PS C:\Temp> 'What is $old?' | ForEach-Object {$_ -replace "\`$old", "(New)"}
What is (New)?
[FAIL] Double quotes as container with backslash-apostrophe as escape:
PS C:\Temp> 'What is $old?' | ForEach-Object {$_ -replace "\'$old", "(New)"}
What is $old?
[SUCCESS] Single quotes as container with simple backslash as escape:
PS C:\Temp> 'What is $old?' | ForEach-Object {$_ -replace '\$old', "(New)"}
What is (New)?
[FAIL] Single quotes as container with backslash-backtick as escape:
PS C:\Temp> 'What is $old?' | ForEach-Object {$_ -replace '\`$old', "(New)"}
What is $old?
Overall, the easiest option may be to use single quotes as the container and a single backslash as the escape: '\$old'
Update 1: Single quotes in function calls are different, requiring no escape. Trying to use an escape on the function call parameter will not work:
[FAIL] Using single quotes plus escape in function parameter:
PS C:\Temp> 'What is $old?' | ForEach-Object {$_.ToString().Replace('\$old', "(New)");}
What is $old?
[SUCCESS] Using single quotes without escape in function parameter:
PS C:\Temp> 'What is $old?' | ForEach-Object {$_.ToString().Replace('$old', "(New)");}
What is (New)?
Update 2: Double quotes in function calls are further different, requiring merely a simple backtick for escape:
[FAIL] Using double quotes with backslash-backtick in function parameter:
PS C:\Temp> 'What is $old?' | ForEach-Object {$_.ToString().Replace("\`$old", "(New)");}
What is $old?
[SUCCESS] Using double quotes with simple backtick in function parameter:
PS C:\Temp> 'What is $old?' | ForEach-Object {$_.ToString().Replace("`$old", "(New)");}
What is (New)?
Upvotes: 25
Reputation: 24071
Instead of messing around with escaping dollar signs, use single quotes '
instead of double quotes "
. It prevents PowerShell expanding $
into a variable. Like so,
$p = "C:\temp\Share\ISO$OEM$"
# Output
C:\temp\Share\ISO$
$p = 'C:\temp\Share\ISO$OEM$'
# Output
C:\temp\Share\ISO$OEM$
If you need to create a path by using variables, consider using Join-Path
. Like so,
$s = "Share"
join-path "C:\temp\$s" '\ISO$OEM$'
# Output
C:\temp\Share\ISO$OEM$
Upvotes: 129
Reputation: 826
You can actually just use a tick mark to escape the $
like so:
`$
Example:
$number = 5
Write-Host "`$${number}"
# Output: $5
Upvotes: 80
Reputation: 65554
In my case I needed to escape some $
's used in a string but not others that are variables.
For example, my SSRS instance name has a $
sign:
[ReportServer$SSRS]
To escape the $ sign I use single quotes. Otherwise I use the -join
statement to concatenate variables with the strings containing actual $ signs.
$sql = -join('ALTER DATABASE [ReportServer$', $instanceName,'TempDB]
SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
GO
USE [master]
RESTORE DATABASE [ReportServer$', $instanceName,'TempDB] FROM DISK = N''C:\temp\ReportServerTempDB.BAK'' WITH FILE = 1,
MOVE N''ReportServerTempDB'' TO N''', $sqlDataDrive + "\data_" + $instanceName, '\ReportServer$', $instanceName,'TempDB.mdf'',
MOVE N''ReportServerTempDB_log'' TO N''', $sqlLogDrive + "\log_" + $instanceName, '\ReportServer$', $instanceName,'_TempDBlog.LDF'', NOUNLOAD, REPLACE, RECOVERY, STATS = 5
GO
ALTER DATABASE [ReportServer$', $instanceName,'TempDB]
SET MULTI_USER;
GO
')
Upvotes: 2