Я просмотрел много документации по правилам экранирования Powershell 5.1, например, тому, что описано в этом ответе и этом другом ответе, но не смог найти способ заставить код со специальными последовательностями символов в строке работать, когда он отправить через cmd и powershell.
Я привел здесь упрощенный пример.
$specialChar = "`nMatch"
$rmtScript = "powershell Write-Output '$specialChar'"
cmd.exe /c $script1
Выдает ошибку:
The string is missing the terminator: '.
+ CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : TerminatorExpectedAtEndOfString
Если я удалю `n в $specialChar, все будет работать нормально.
Любые предложения о том, как решить эту проблему?
Обновлено: Моя конечная цель — отправить сценарий через ssh, который записывает в файл, например:
$specialChar = "`nMatch all`n"
$rmtScript = "powershell Add-Content -Force -Verbose " +
"-Path c:\ProgramData\ssh\sshd_config -Value '$specialChar'"
ssh $Username@$ComputerIP $rmtScript
Сценарий должен изменить файл в Path в формате, заданном с помощью специальных последовательностей символов, поэтому создайте новую строку, напишите слова и новую строку. Этот код и добавленный мной упрощенный пример при выполнении отправляют одно и то же сообщение об ошибке.
@mklement0 Где ты нашел эту информацию? Из командной строки я получаю помощь cmd /? /C Carries out the command specified by string and then terminates
@JackOA, цитируемая информация недостаточно подробна. Вы можете убедиться, что это не работает, попробовав cmd /c "echo a`nb"
и cmd /c "echo a^`nb"
, оба из которых печатают только a
(использование `r`n
тоже не помогает).
@mklement0 Спасибо за ваш комментарий, но я не уверен, что то, что вы подразумеваете под цитируемой информацией, недостаточно подробно. Кроме того, ваши примеры не отражают мою проблему, поскольку после cmd /c
вызывается команда powershell
, которая форматирует строку. Вы можете попробовать cmd /c "powershell Write-output 'ab'"
vs cmd /c "powershell Write-output 'a
nb'"`, чтобы воссоздать заданную проблему.
@JackOA: Я имел в виду, что цитата из документации недостаточно подробна: в ней не упоминается фактическое однострочное ограничение. Мои примеры по-прежнему применимы, потому что cmd.exe
всегда неправильно обрабатывает многострочную строку, независимо от того, какую команду вы передаете /c
. Надеюсь, мой ответ внесет ясность.
Вы принципиально не можете передать многострочную команду cmd /c
[1] и, если предположить, что интересующая вас команда ssh
нацелена на компьютер с Windows, который использует оболочку по умолчанию, [2] которая также является cmd.exe
, у вас возникнет та же проблема.
Обходной путь:
Избегайте буквальных символов новой строки в команде PowerShell, отложив раскрытие escape-последовательности `n
и позволив целевому экземпляру PowerShell расширить ее:
# Note the use of '...' here, to prevent up-front expansion of `n
$specialChar = '`nMatch'
# Note the use of embedded \"...\", to ensure that `n is expanded by PowerShell
$rmtScript = "powershell Write-Output \`"$specialChar\`""
cmd.exe /c $rmtScript
Альтернативно используйте $([char 10])
или [char] 10
в выражениях.
Предостережения:
В зависимости от того, из какой редакции/версии PowerShell вы звоните, вам может потребоваться дополнительное экранирование встроенных символов "
. при вызове ssh.exe
, а не напрямую cmd.exe /C
.
Вышеуказанное надежно работает со специальными символами, отличными от символов новой строки, в значении $specialChar
, но делает значение подлежащим нормализации пробелов; например, foo bar
станет foo bar
.
Чтобы избежать этого при вызове cmd.exe /C
(что косвенно относится и к вызовам ssh.exe
при настройке компьютеров Windows с конфигурацией оболочки по умолчанию), сохраняя при этом надежность вызова, заключите общий (подразумеваемый) аргумент -Command
в "..."
и заключите $specialChar
в "^""..."^""
( sic), с дополнительным предварительным экранированием символов "
. как `"
в данном случае.
""
.Поэтому:
$rmtScript = "powershell -NoProfile `"Write-Output `"^`"`"$specialChar`"^`"`"`""
См. этот ответ для получения дополнительной информации.
[1] You can verify this as follows from PowerShell: cmd /c "echo a`nb"
and cmd /c "echo a^`nb"
both print just a
(and using `r`n
doesn't help either), i.e. the 2nd line is ignored. Therefore, something like cmd /c "powershell -c 'a`nb'"
executes a syntactically broken command, powershell -c 'a
, resulting in the error you saw.
[2] However, a target server's default shell is configurable from there, and it is possible to make PowerShell the default shell, in which case you can specify PowerShell code directly in an ssh
call, and you're also not subject to the single-line constraint; see the docs.
@JackOA Не видя конкретной командной строки, я не уверен, в чем проблема. Итак, да, пожалуйста, откройте новый вопрос, не в последнюю очередь потому, что было бы полезно знать, необходимо ли соблюдать дополнительные правила при передаче командной строки в ssh
.
Обратите внимание, что вы можете передавать только однострочные командные строки
cmd /c