PowerShell: экранирование правил для вызовов CLI с помощью специальных последовательностей символов

Я просмотрел много документации по правилам экранирования 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 в формате, заданном с помощью специальных последовательностей символов, поэтому создайте новую строку, напишите слова и новую строку. Этот код и добавленный мной упрощенный пример при выполнении отправляют одно и то же сообщение об ошибке.

Обратите внимание, что вы можете передавать только однострочные командные строки cmd /c

mklement0 07.08.2024 00:04

@mklement0 Где ты нашел эту информацию? Из командной строки я получаю помощь cmd /? /C Carries out the command specified by string and then terminates

JackOA 07.08.2024 11:49

@JackOA, цитируемая информация недостаточно подробна. Вы можете убедиться, что это не работает, попробовав cmd /c "echo a`nb" и cmd /c "echo a^`nb", оба из которых печатают только a (использование `r`n тоже не помогает).

mklement0 07.08.2024 12:54

@mklement0 Спасибо за ваш комментарий, но я не уверен, что то, что вы подразумеваете под цитируемой информацией, недостаточно подробно. Кроме того, ваши примеры не отражают мою проблему, поскольку после cmd /c вызывается команда powershell, которая форматирует строку. Вы можете попробовать cmd /c "powershell Write-output 'ab'" vs cmd /c "powershell Write-output 'anb'"`, чтобы воссоздать заданную проблему.

JackOA 07.08.2024 19:43

@JackOA: Я имел в виду, что цитата из документации недостаточно подробна: в ней не упоминается фактическое однострочное ограничение. Мои примеры по-прежнему применимы, потому что cmd.exe всегда неправильно обрабатывает многострочную строку, независимо от того, какую команду вы передаете /c. Надеюсь, мой ответ внесет ясность.

mklement0 07.08.2024 20:31
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
5
62
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы принципиально не можете передать многострочную команду 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.

mklement0 08.08.2024 12:22

Другие вопросы по теме