tl; dr
Ваша полная "..."
-замкнутая строка JSON имеет внедренный "
, который должен быть экранирован как \"
(sic;Упрощенная команда):
powershell.exe -File "C:\...\customscript.PS1" ... -jsonContent "{ \"c\": \"some setting\", \"d\": \"unknown\", \"b\": \"some thing\", \"a\": 1 }"
Читайте, когда требуется дополнительное экранирование, чем отличается вызов -File
от вызова -Command
и как вызывающая оболочка (откуда вы вызываете powershell.exe
)имеет значение.
Примечание:
В этом ответе в основном рассматривается использование исполняемого файла Windows PowerShell , powershell.exe
, но он применяется аналогичнов PowerShell Core , pwsh
, и внизу есть раздел о вызовах из bash
.
Раздел Вызов из PowerShellСам ниже, в частности, синтаксис, необходимый для -File
, применяется для передачи JSON и другим программам, таким как curl.exe
.
Требуемый синтаксис дляPowerShell CLI - то есть вызов powershell.exe
с аргументами - зависит от :
независимо от того, звоните ли вы из cmd.exe
(командная строка / пакетный файл) или из самой PowerShell (или, в PowerShell Core из POSIX-подобной оболочки, такой как bash
).
передаете ли вы аргументы powershell -Command
(встроенная команда) или
powerShell -File
(путь к сценарию).
В любом случае, ваша первоначальная попытка не могла бы сработать, потому что литерал { "c": "some setting" ... }
не может быть распознан как единственный аргумент , поскольку содержит пробелы и не заключено в кавычки в целом;команда, добавленная позже, с включением "..."
, не содержит экранирования встроенного "
.
Следующие команды демонстрируют необходимый синтаксис для обсуждаемых сценариев с использованием упрощенной строки JSON.
Чтобы сделать команды -File
работающими, создайте файл script.ps1
в текущем каталоге.со следующим содержанием: ConvertFrom-Json $Args[0]
Вызов из cmd.exe
/ пакетный файл
Встроенный "
должен быть экранирован как \"
(хотя PowerShell- внутри вы бы использовали `"
).
Важно:
Если текст JSON содержит cmd.exe
метасимволы (неизменно между \"...\"
запусками), вы должны ^
- оставить их отдельно , потому что cmd.exe
, из-за того, что \"
не распознается как экранированный "
, считает эти подстроки без кавычек ;например, \"some & setting\"
должен быть экранирован как \"some ^& setting\"
;метасимволы cmd.exe
, которые здесь необходимо экранировать:
& | < > ^
cmd.exe
в стиле ссылки на переменные окружения , такие как %USERNAME%
являются интерполированными - cmd.exe
не имеет буквального строкового синтаксиса, он распознает только "..."
, где интерполяция имеет место , так же, какв без кавычек токенов.
Если вы хотите передать такой токен как есть, т. е. подавить интерполяцию, синтаксис экранирования зависит от того, вызываете ли вы из командная строка или командный файл , к сожалению: используйте %^USERNAME%
от первого и %%USERNAME%%
от второго - см. этот ответ для подробностей.
Обратите внимание, что вызовы -Command
просто добавляют еще один уровень цитирования, заключая строку "..."
в '...'
.Это необходимо, потому что с -Command
PowerShell обрабатывает полученные аргументы как PowerShell с исходным кодом , а не как буквальные аргументы (последнее происходит с -File
);если бы не вложение '...'
, общее вложение "..."
было бы лишено до интерпретации.
с -File
:
# With a literal string:
powershell -File ./script.ps1 "{ \"c\": \"some setting\", \"unknown\": \"b\" }"
# With an expandable string (expanded by the caller):
powershell -File ./script.ps1 "{ \"c\": \"some %USERNAME%\", \"unknown\": \"b\" }"
С -Command
:
# With a literal string:
powershell -Command ConvertFrom-Json '"{ \"c\": \"some setting\", \"unknown\": \"b\" }"'
# With an expandable string (expanded by the caller):
powershell -Command ConvertFrom-Json '"{ \"c\": \"some %USERNAME%\", \"unknown\": \"b\" }"'
Вызов из самой PowerShell
При вызове из PowerShell отпадает необходимость избегать cmd.exe
метасимволов, потому что cmd.exe
не задействован.
Применяются правила цитирования строк в PowerShell, что упрощает ситуацию, хотя, к сожалению, вам все еще нужно вручную \
-внешний встраивать "
символы. ;см. эту проблему GitHub для фона.
Использование внешнего цитирования '...'
упрощает синтаксис для встроенного цитирования, но это ограничивает вас передачей literal строки.
Использование внешнего "..."
позволяет встраивать переменные ссылки и выражения из вызывающей стороны (которые перед вызовом вызывают , до аргумент передается), но это усложняет синтаксис, учитывая, что встроенный "
должен затем вдвойне экранироваться как \`"
(sic): сначала с `
, чтобы соответствовать PowerShell- внутренний синтаксис, затем с \
для удовлетворения требований PowerShell CLI .
Если текст JSON не является литераломи сохраненные в переменной , вы должны передать
$jsonVar -replace '"', '\"'
для выполнения необходимого экранирования - см. этот ответ .
С -File
или при вызове внешних программ , таких как curl.exe
:
# With a literal string:
powershell -File ./script.ps1 '{ \"c\": \"some setting\", \"unknown\": \"b\" }'
# With an expandable string (expanded by the caller):
powershell -File ./script.ps1 "{ \`"c\`": \`"some $env:OS\`", \`"unknown\`": \`"b\`" }"
С -Command
:
# With a literal string:
powershell -Command ConvertFrom-Json '''"{ \"c\": \"some setting\", \"unknown\": \"b\" }"'''
# With an expandable string (expanded by the caller):
powershell -Command ConvertFrom-Json "'{ \`"c\`": \`"some $env:OS\`", \`"unknown\`": \`"b\`" }'"
PowerShell Ядро : вызов из bash
Bash, как и PowerShell, понимает как расширяющиеся (интерполяционные) "..."
строки, так и буквальные '...'
строки.
Bash, в отличие от cmd.exe
, распознает \"
как сбежал "
символов.внутри "..."
, поэтому нет необходимости избегать метасимволов Баша.
С -File
:
# With a literal string:
pwsh -File ./script.ps1 '{ "c": "some setting", "unknown": "b" }'
# With an expandable string (expanded by the caller):
pwsh -File ./script.ps1 "{ \"c\": \"some $USER\", \"unknown\": \"b\" }"
С -Command
:
# With a literal string:
pwsh -Command ConvertFrom-Json \''{ "c": "some setting", "unknown": "b" }'\'
# With an expandable string (expanded by the caller):
pwsh -Command ConvertFrom-Json "'{ \"c\": \"some $USER\", \"unknown\": \"b\" }'"