2011-12-12 2 views
14

나는 다음과 같은 Windows 배치 코드를 가지고 그것을 실행하는 경우 :(윈도우 배치) 고토 블록은 매우 이상하게 행동하면 내

echo foo 
if 1 == 1 (
    echo bar 
    goto asdf 
    :asdf 
    echo baz 
) else (
    echo quux 
)

을 내가 기대 출력은 다음과 같습니다

foo 
bar 
baz

하지만 그 대신 내가 얻은 :

foo 
bar 
baz 
quux

goto asdf 줄을 주석으로 처리하면 예상 한 결과를 얻을 수 있습니다. echo quux 라인을 절대로 발췌해서는 안되며, 왜 고토의 존재가 그 원인이됩니까?

UPDATE :

goto BEGIN 

:doit 
    echo bar 
    goto asdf 
    :asdf 
    echo baz 
    goto :EOF 

:BEGIN 

echo foo 
if 1 == 1 (
    call :doit 
) else (
    echo quux 
)

그러나,이 내 원래의 질문에 대답하지 않습니다 : 그것은 가치가 무엇인지에 대한, 여기에 제대로 내가 원래 의도 않는 문제를 해결합니다.

답변

23

CALL 또는 GOTO의 대상이 괄호 안에있는 블록 문의 내부에 없어야합니다. 그것은 할 수 있지만 보시다시피, 결과는 아마도 당신이 원하는대로되지 않을 것입니다.

전체 IF (...) ELSE (...) 구문은 처리되기 전에 구문 분석되어 메모리에로드됩니다. 다른 단어에서는 논리적으로 한 줄의 코드로 취급됩니다. 구문 분석이 끝나면 CMD.EXE는 IF/ELSE 구문 뒤에 다음 줄부터 구문 분석을 다시 시작하려고합니다.

구문 분석 단계 후 복잡한 명령이 메모리에서 실행됩니다. IF 절이 제대로 처리되고 ELSE 절이 제대로 건너 뜁니다. 그러나 IF (참) 절에서 GOTO :asdf을 수행하면 CMD.EXE가 레이블 검색을 시작합니다. IF/ELSE의 끝에서 시작하여 파일의 맨 아래로 스캔하고 맨 위로 돌아가서 레이블을 찾을 때까지 스캔합니다. 레이블은 IF 절 내에있게되지만 레이블 스캐너는 그 세부 사항에 대해 아무것도 모릅니다. 따라서 복잡한 명령이 메모리에서 실행을 끝내면 복잡한 IF/ELSE의 끝에서부터 레이블 대신 일괄 처리가 다시 시작됩니다.

그래서이 시점에서 일괄 처리 프로세서는보고 다음 몇 줄

echo baz 
) else (
    echo quux 
) 

바즈가 반향되어 실행 등 quux입니다. 하지만 당신은 왜 ) else (을하지 않습니다 및/또는 그들이 지금 불균형 더 이상 큰 IF 문의 일부로 해석 때문에 )에 구문 오류가 발생 ", 요청할 수 있습니다?

때문에 처리하는 방법을 )이다

.

)가 발생하는 경우, 다음 )은 당신이 기대하는 것처럼.

처리되지만 활성 오픈 (가있는 경우 파서가 명령을 기대하고 적극적인 개방 (가없는 경우 )를 발견하는 경우, 다음 )은 무시되고 나머지 줄의 모든 문자는 무시됩니다! 실제로 )은 REM 문으로 작동합니다.

+2

+1 좋은 설명, Dave. 더 짧은 것 :'GOTO'가 실행될 때 * 활성화 *'FOR/IF' 명령이 취소되고 배치 파일은 라벨에서 계속됩니다. – Aacini

5

대괄호 안의 모든 것은 한 줄로 처리되고 처리되며 해석되고 한 번에 실행됩니다.스크립트가 goto asdf에 도달하여 해당 블록/라인 밖으로 점프합니다. :asdf 레이블에는 괄호가 없으므로 선을 하나씩 읽기 시작합니다. else에 도달하지만 :asdfelse 사이에 if이 없으므로이를 무시합니다.

이와 같은 문제를 방지하기 위해 블록이 아닌 iffor 문에 항상 goto 또는 call을 사용합니다. 이것은 goto 문장으로 문제를 분류하고 변수에 대해서도 많은 문제를 분류합니다.

goto를 사용하려면 다음과

echo foo 
if 1 == 1 goto bar 
echo quux 
goto nextbit 

:bar 
echo bar 
goto asdf 
:asdf 
echo baz 

:nextbit 
:: more script... 

또는 call을 사용 :

echo foo 
if 1 == 1 (call :bar) else (call :quux) 
:: more script... 
exit /b 

:bar 
echo bar 
goto asdf 
:asdf 
echo baz 
exit /b 

:quux 
echo quux 
exit /b 
0

를가 IF 문 내부 루프의 가난한 중첩 및 구조에 관련이있는 것으로 판명이 경우, 위의 https://stackoverflow.com/users/1012053/dbenham에 의해 명확하게 설명되어 있습니다.

말하기를, 내가 다른 유사한 고려 사항을 알아 냈 때문에이 문제에 ... 는 살펴주십시오 다음과 같은 문제가 여기에 이후의 솔루션 : ". was unexpected at this time" generated from batch script line 'if exist [file] (...

이 솔루션은 단순히 '('의 치료했다 IF 문 블록 내부의 ECHO 행에 ')'를 입력하십시오.

요점은 IF (및 아마도 FOR) 문구를 해결할 때 문제의 가능한 원인으로 특수 문자의 처리를 고려하는 것입니다.

HTH

관련 문제