Уклонение от знака доллара на пути powershell не работает

Почему это не работает?


$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

Эхо показывает правильный путь, но команда Get-Content расширяет $oem и $1 до пустых строк, даже если они экранированы?

Ответ 1

Вместо того, чтобы возиться с побеждающими знаками доллара, используйте одинарные кавычки ' вместо двойных кавычек ". Это предотвращает расширение Powershell $ в переменную. Таким образом,

$p = "C:\temp\Share\ISO$OEM$"
# Output
C:\temp\Share\ISO$


$p = 'C:\temp\Share\ISO$OEM$'
# Output
C:\temp\Share\ISO$OEM$

Если вам нужно создать путь с помощью переменных, рассмотрите возможность использования Join-Path. Таким образом,

$s = "share"
join-path "c:\temp\$share" 'Share\ISO$OEM$'
# Output
c:\temp\Share\ISO$OEM$

Ответ 2

Вы использовали двойные кавычки с одной обратной стороной. Это неправильная комбинация. На самом деле, я не уверен, что в любом случае достаточно одного обратного хода. Ваши успешные варианты, позволяющие избежать знака доллара ($) в PowerShell, заключаются в использовании двойных кавычек с комбинацией backslash-backtick ( "\` $find" ) или вместо этого использовать одинарные кавычки с простой обратной косой чертой ( '\ $находкой'). [Однако обратите внимание на исключение в конце о параметрах вызова функции.] Ниже приведены примеры.

Кроме того, для тех, кто не знаком с различием, важно не путать символ обратного хода (`) с одинарной кавычкой символ (') в этих экранах.

[УСПЕХ] Двойные кавычки как контейнер с обратным слэшем-обратным шагом в качестве escape-кода:

PS C:\Temp> 'What is $old?' | ForEach-Object {$_ -replace "\`$old", "(New)"}
What is (New)?
PS C:\Temp>

[FAIL] Двойные кавычки в качестве контейнера с обратным слэшем-апострофом как escape:

PS C:\Temp> 'What is $old?' | ForEach-Object {$_ -replace "\'$old", "(New)"}
What is $old?
PS C:\Temp>

[УСПЕХ] Одиночные кавычки как контейнер с простой обратной косой чертой как побег:

PS C:\Temp> 'What is $old?' | ForEach-Object {$_ -replace '\$old', "(New)"}
What is (New)?
PS C:\Temp>

[FAIL] Одиночные кавычки в качестве контейнера с обратным слэшем в качестве выхода:

PS C:\Temp> 'What is $old?' | ForEach-Object {$_ -replace '\`$old', "(New)"}
What is $old?
PS C:\Temp>

В целом самым простым вариантом может быть использование одинарных кавычек в качестве контейнера и один обратный слэш в качестве escape: '\$old'

Обновить. Как если бы приведенные выше не были достаточно сложными, когда вы используете вызов функции вместо команды, нужны одиночные кавычки без выхода. Попытка использовать escape на параметре вызова функции не будет работать:

[FAIL] Использование escape-функции в параметре функции:

PS C:\Temp> 'What is $old?' | ForEach-Object {$_.ToString().Replace('\$old', "(New)");}
What is $old?
PS C:\Temp>

[УСПЕХ] Использование простых одинарных кавычек без escape-функции в параметре функции:

PS C:\Temp> 'What is $old?' | ForEach-Object {$_.ToString().Replace('$old', "(New)");}
What is (New)?
PS C:\Temp>

Ответ 3

В моем случае мне нужно было избегать использования $ используемого в строке, но не других переменных.

Например, у моего имени экземпляра SSRS есть знак $:

[ReportServer $ SSRS]

Чтобы избежать знака $, я использую одинарные кавычки. В противном случае я использую -join для объединения переменных со строками, содержащими действительные знаки $.

 $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
  ')