앰퍼샌드(&)가 포함된 변수인 매개변수를 사용하여 서브루틴을 어떻게 호출합니까?
오류는 없지만 호출이 실행되지 않는 것 같습니다.
example.bat
@echo off
setlocal enableDelayedExpansion
rem Doesn't work
set val=with^&ersand
call :Output !val!
rem Works fine
set val=without_ampersand
call :Output !val!
goto End
:Output
set "line=%1"
echo Called: !line!
goto :eof
End:
산출:
호출됨: Without_ampersand
편집하다:
사용법지연된 확장필요하지 않습니다. 이 예에서는 방금 사용되었습니다. DelayedExpansion을 사용하지 않고 이를 수행하는 방법이 선호됩니다.
문제는 "처음에 변수를 어떻게 설정합니까?"보다는 "어떻게 호출합니까?"에 초점을 맞추고 있습니다. 변수는 사용자 입력이나 for /f
루프(제 경우와 마찬가지로)에서 나올 수 있습니다.
답변1
일괄 이스케이프 규칙은 매우 불쾌하지만 규칙을 알고 있으면 동작을 완전히 예측할 수 있습니다.
문제를 이해하는 데 필요한 정보는 다음에서 확인할 수 있습니다.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%%&ersand"
call :Output !val!
rem Calling with a string literal
call :Output with%%ESC%%^&ersand
exit /b
:Output
set "line=%1"
echo Called: !line!
goto :eof
ESC는 ^
.
1단계의 첫 번째 라운드는 1단계의 두 번째 라운드(6단계에서 시작) %%ESC%%
로 확장됩니다 .%ESC%
%ESC%
^
이는 완전히 비실용적입니다. 특히 내용이 어떻게 될지 모르는 경우에는 더욱 그렇습니다.
CALLed 루틴에 값을 안정적으로 전달하는 유일한 합리적인 전략은 참조로 전달하는 것입니다. 문자열 값이 포함된 변수의 이름을 전달하고 지연된 확장을 사용하여 서브루틴 내에서 해당 값을 확장합니다.
@echo off
setlocal enableDelayedExpansion
set "val=with&ersand"
call :Output val
exit /b
:Output
set "line=!%~1!"
echo Called: !line!
exit /b
답변2
추가 ^
및 따옴표를 추가하면 작동합니다.
@echo off
setlocal enableDelayedExpansion
rem Doesn't work
set "val=with^^&ersand"
call :Output !val!
rem Works fine
set "val=without_ampersand"
call :Output !val!
goto End
:Output
set "line=%1"
echo Called: !line!
goto :eof
SET LOCAL EnableDelayedExpansion
2개의 이스케이프 문자가 필요합니다.
ECHO 123 ^^& 456^^!
출력됩니다 123 & 456!
.
SET
또한 항상 따옴표와 함께 사용해야 합니다 !
답변3
&가 여전히 명령 구분 기호로 읽혀지기 때문에 다른 답변은 작동하지 않았지만 다음을 생각해 냈습니다. 마지막 for 루프는 데모용이며 필요에 따라 수정하거나 제거해야 합니다.
@echo off
setlocal enableDelayedExpansion
set "file=pathwith&orwithoutampersandand!exclamation"
call :execute
exit /b
:execute
for %%A in ("%file:!=" "%") do (
if [!file_conc!]==[] (
set "file_conc=%%A"
) else (
set "file_conc=!file_conc!^^^!%%A"
)
)
set "file=!file_conc:"=!"
set "file_conc="
for %%A in ("!file:&=" "!") do (
if [!file_conc!]==[] (
set "file_conc=%%A"
) else (
set "file_conc=!file_conc!^^^&%%A"
)
)
set "file=!file_conc:"=!"
set "file_conc="
for /f "tokens=*" %%A in ('cmd /c ""!file!" "%error_log%" %ldt%" 1^>nul') do stuff
exit /b
답변4
따옴표 안에는 독 문자가 <>|&
안전합니다. 매번 따옴표를 사용해야 하고, 이를 처리(정의 또는 사용)(또는 이스케이프)해야 합니다. 이는 set
명령(변수 정의)으로 시작하여 매개변수(변수 사용법)까지 계속되고 명령(변수 사용법) call
으로 계속됩니다(그러나 아직 끝나지 않음) .echo
@echo off
setlocal
set "val=with&ersand"
call :Output "%val%"
exit /b
:Output
set "line=%~1"
set line
echo problem without quotes: %line%
echo ok with quotes: "%line%"
echo ok with escaping: %line:&=^&%
for /f "delims=" %%a in ("%line%") do echo ok with for: %%a
산출:
line=with&ersand
problem without quotes: with
Der Befehl "ampersand" ist entweder falsch geschrieben oder
konnte nicht gefunden werden.
ok with quotes: "with&ersand"
ok with escaping: with&ersand
ok with for: with&ersand