tl; dr
Примечание. Следующее не решает проблему c OP (причина которой пока неизвестна), но мы надеемся содержит информацию, представляющую общий интерес.
# Use "" to escape " and - in case of delayed expansion - ^! to escape !
$param = '{ ""job_start"": ""jdbc:mysql://127.0.0.1:3307/test&serverTimezone=UTC&more^!"" }'
- Существуют высокопрофильные утилиты (CLI), такие как
az
(Azure), основанные на Python , но на Windows используйте вспомогательный командный файл в качестве исполняемого файла, который просто передает аргументы сценарию Python. - Используйте
Get-Command az
, например, чтобы узнать полное имя исполняемого файла; пакетные файлы, которые обрабатываются cmd.exe
, устаревшим командным процессором, имеют расширение имени файла .cmd
или .bat
- Чтобы предотвратить вызовы такого командного файла из взлом, двойные кавычки, встроенные в аргументы, переданные из PowerShell, должны быть экранированы как
""
- Дополнительно, но только в том случае, если
setlocal enabledelayedexpansion
действует в данном целевом пакетном файле или если ваш компьютер настроен на использование отложенного расширения по умолчанию , для все командные файлы: !
символы должны быть экранированы как ^!
, который, однако, эффективен только в том случае, если cmd.exe
учитывает !
часть строки с двойными кавычками.
Похоже, что у нас есть сочетание двух проблем :
A PowerShell проблема с "
символами. встроенный в аргументы, передаваемые внешним программам :
- В идеальном мире передача JSON текста, такого как
'{ "foo": "bar" }'
, в внешняя программа будет работать как есть , но из-за неработающей обработки PowerShell встроенных двойных кавычек , то есть недостаточно , и "
символов. необходимо дополнительно экранировать для программы target либо как \"
(которое поддерживает большинство программ), либо, в случае cmd.exe
(см. ниже), как ""
, который Python, к счастью, тоже распознает: '{ ""foo"": ""bar"" }'
Ограничения передачи аргументов и экранирования в cmd.exe
пакете files :
Похоже, spark-submit
- это вспомогательный пакетный файл (.cmd
или .bat
), который передает аргументы через в сценарий Python.
Проблема в том, что , если вы используете \"
для экранирования встроенного "
, cmd.exe
не 'не распознает их как экранированный , что заставляет его рассматривать символы &
без кавычек , и поэтому они интерпретируются как метасимволы оболочки , т.е. как символы со специальной функцией синтаксиса c (в данном случае последовательность команд).
Дополнительно и только если setlocal enabledelayedexpansion
действует в для данного командного файла любые буквальные !
символы в аргументах требуют дополнительной обработки:
Если cmd.exe
считает, что !
является частью аргумент без кавычек , вы не можете избежать !
вообще.
Внутри аргумента в кавычках (что неизменно означает "..."
в cmd.exe
) , вы должны экранировать буквальный !
как ^!
.
Обратите внимание, что это требование является инверсией того, как все другие метасимволы должны быть экранированы (что требует ^
, когда без кавычек , но не внутри "..."
).
К сожалению, вам необходимо знать детали реализации целевого пакетного файла - использует ли он setlocal enabledelayedexpansion
или нет - чтобы правильно сформулировать ваши аргументы.
То же применимо, если ваш компьютер настроен на использование отложенного расширения по умолчанию , для все командные файлы (и в интерактивном режиме), что не является обычным и не рекомендуется. Чтобы проверить, настроен ли данный компьютер таким образом, проверьте выходные данные следующей команды для DelayedExpansion : 1
: если выходных данных нет вообще, отложенное раскрытие отключено; если есть 1 или 2 выхода, отложенное расширение включено по умолчанию, если первый или только выводит отчеты DelayedExpansion : 1
.
Get-ItemProperty -EA Ignore 'registry::HKEY_CURRENT_USER\Software\Microsoft\Command Processor', 'registry::HKEY_LOCAL_MACHINE\Software\Microsoft\Command Processor' DelayedExpansion
Обходной путь :
Поскольку вы технически вызываете командный файл, используйте ""
чтобы избежать буквального "
символов. внутри строки PowerShell в одинарных кавычках ('...'
).
Если вы знаете, что целевой пакетный файл использует setlocal enabledelayedexpansion
или , если ваш компьютер настроен на использовать отложенное раскрытие по умолчанию , экранировать !
символы как ^!
- Обратите внимание, что это эффективно, только если
cmd.exe
учитывает !
часть двойного- строка в кавычках.
Поэтому (обратите внимание, что я расширил URL-адрес, включив токен с !
, который должен передаваться буквально как суффикс more!
):
$param = '{ ""job_start"": ""jdbc:mysql://127.0.0.1:3307/test&serverTimezone=UTC&more^!"" }'
Если вам нужно избежать существующей JSON строки программно :
# Unescaped JSON string, which in an ideal world you'd be able
# to pass as-is.
$param = '{ "job_start": "jdbc:mysql://127.0.0.1:3307/test&serverTimezone=UTC&more!" }'
# Escape the " chars.
$param = $param -replace '"', '""'
# If needed, also escape the ! chars.
$param = $param -replace '!', '^!'
В конечном итоге , обе проблемы должны быть исправлены в источнике - но это маловероятно, поскольку нарушит обратную совместимость .
Что касается PowerShell, этот выпуск GitHub содержит предысторию, технические детали, надежную функцию-оболочку, чтобы скрыть p проблемы и обсуждения того, как решить проблему, по крайней мере, на основе согласия.