Как передать параметр с амперсандом при вызове пакета из пакета - PullRequest
2 голосов
/ 27 марта 2020

foo.bat:

call qwe.bat "hello && bye"

qwe.bat:

@echo off
set cmd=%~1
echo "%cmd%"

Когда я выполняю foo.bat, я получаю ошибку:

'bye' is not recognized as an internal or external command,
operable program or batch file.
"hello "

Итак как передать строку "hello && bye" из foo.bat в qwe.bat? Похоже, проблемы возникают из-за амперсандов *

Ответы [ 2 ]

2 голосов
/ 27 марта 2020

Правила пакетного удаления довольно неприятны, но поведение полностью предсказуемо, если вы знаете правила.

Информация, необходимая для понимания проблемы, доступна в разделе Как интерпретатор команд Windows (CMD) .EXE) разбирать скрипты? на этапах 1, 2, 5 и 6 принятого ответа. Но удачи, поглощая эту информацию в ближайшее время: -)

Есть две фундаментальные проблемы дизайна, которые приводят к вашей проблеме: - Фаза 6 удваивает все каретки, а затем перезапускает фазу 2 (фактически фазы 1, 1.5 и 2). ). - Но фаза 2 требует & быть экранирована как ^ &. Обратите внимание, что это должен быть один ^, а не удвоенный!

Единственный способ получить ваш подход к работе - ввести ^ после удвоения каретки фазы 6.

@echo off
setlocal enableDelayedExpansion
set "ESC=^"

rem Calling with delayed expansion value
set "val=with%%ESC%%&ampersand"
call :Output !val!

rem Calling with a string literal
call :Output with%%ESC%%^&ampersand

exit /b

:Output
set "line=%1"
echo Called: !line!
goto :eof

ES C определено для хранения ^. Первый раунд фазы 1 расширяет %% ESC %% до% ESC%, второй раунд фазы 1 (инициированный фазой 6) расширяет% ESC% до ^

Это все практически нецелесообразно, особенно если вы не Не знаю, каким будет содержимое.

Единственная разумная стратегия для надежной передачи любого значения в процедуру CALLed - это передача по ссылке. Передайте имя переменной, содержащей строковое значение, и разверните это значение в своей подпрограмме, используя отложенное расширение.

@echo off
setlocal enableDelayedExpansion
set "val=with&ampersand"
call :Output val
exit /b

:Output
set "line=!%~1!"
echo Called: !line!
exit /b
1 голос
/ 27 марта 2020

После определения вашей переменной с использованием рекомендованного синтаксиса, Set "Var=String Value", вы можете просто использовать отложенное расширение:

@Echo Off
Set "Cmnd=%~1"
SetLocal EnableDelayedExpansion
Echo !Cmnd!
Pause
EndLocal
...