goto label(배치 파일) Windows에 대해 혼란스러워함

goto label(배치 파일) Windows에 대해 혼란스러워함

이 명령을 이런 식으로 사용하면 다음과 같은 작업이 수행됩니다.

만약에foo ~였다이전에 한 가지 또는 다른 것으로 설정한 경우 다음으로 건너뜁니다.foobar_menu

foo이전에 그랬 다면~ 아니다(동일한) 것으로 설정하면 다음으로 건너뜁니다.another_menu

rem Check if foo was previously set as bar1 or bar2...
if "%foo%"=="bar1" goto :foobar_menu
if "%foo%"=="bar2" goto :foobar_menu

rem Check if foo was NOT previously set as bar1 or bar2...
if not "%foo%"=="bar1" goto :another_menu
if not "%foo%"=="bar2" goto :another_menu

혼란스러운 이유는 다음과 같습니다. 아래 그림과 같이 교체하면 제대로 작동하지 않고 잘못된 라벨로 이동합니다. 그런데 왜 그럴까요?

rem Check if foo was NOT previously set as bar1 or bar2...
if not "%foo%"=="bar1" goto :another_menu
if not "%foo%"=="bar2" goto :another_menu

rem Check if foo was previously set as bar1 or bar2...
if "%foo%"=="bar1" goto :foobar_menu
if "%foo%"=="bar2" goto :foobar_menu

왜 이 두 가지가 같은 일을 하지 않는 걸까요?

goto 부분을 괄호 안에 넣지 않기 때문입니까?

나는 그것을 작동하게 했지만(첫 번째 방법) 그것은 내 메뉴가 들어가는 순서와 같지 않으며 위의 두 번째(작동하지 않는) 예에 배치된 방식으로 모든 것이 실행되기를 원했습니다.

건배.

편집하다:

실제 명령은 다음과 같습니다. 이렇게 배치하면 중첩되어 있더라도 choose_audio_sample_rate변수 아래에 opus 또는 libopus가 설정되어 있어도 여전히 레이블로 이동합니다 .

if not "%audio_codec%"=="libopus" if not "%audio_codec%"=="opus" goto :choose_audio_sample_rate
if "%audio_codec%"=="libopus" if "%audio_codec%"=="opus" goto :choose_audio_sample_rate_opus

실제로 스왑된 버전도 작동하지 않으며 choose_audio_sample_rate변수 아래에 opus 또는 libopus가 설정되어 있어도 작동합니다.

if "%audio_codec%"=="libopus" if "%audio_codec%"=="opus" goto :choose_audio_sample_rate_opus
if not "%audio_codec%"=="libopus" if not "%audio_codec%"=="opus" goto :choose_audio_sample_rate

여기 미치광이로 변하고 있어요 ㅋㅋㅋ, 좋아요, 이것만 사용하면 작동합니다(그리고 opus가 아닌 메뉴로 바로 전달됩니다):

if "%audio_codec%"=="libopus" (goto :choose_audio_sample_rate_opus)
if "%audio_codec%"=="opus" (goto :choose_audio_sample_rate_opus)

libopus라면 오른쪽 라벨로 이동합니다. libopus가 아니면 다음 줄이 처리되고, opus라면 오른쪽 레이블로 이동합니다.

그 이상이면 libopus나 opus도 아니고 일반 메뉴로 넘어갑니다.

답변1

배치 파일은 위에서 아래로 실행됩니다.

foo2두 번째 예에서는 또는 가 설정되어 있어도 foo1항상 로 이동합니다 :another_menu. 배치 파일이 두 명령문을 지나 이동하는 유일한 방법은 둘 다 설정된 경우 foo1입니다 foo2.

본질적으로 논리적 OR 상황을 생성하고 있습니다.

foo1 또는 foo2가 설정되지 않은 경우 another_menu로 이동하세요.

또 다른

foo1 또는 foo2가 설정된 경우 foobar_menu로 이동하세요.

또 다른

아무것도하지 마세요

첫 번째 예에 비해,

foo1 또는 foo2가 설정된 경우 foobar_menu로 이동하세요.

또 다른

foo1 또는 foo2가 설정되지 않은 경우 another_menu로 이동하세요.

또 다른

아무것도하지 마세요

필요한 것은 특히 논리적 AND입니다. 배치 파일 IF 문은 AND 또는 OR을 지원하지 않습니다. 따라서 다음과 같이 중첩하거나 연결합니다.

if not "%foo1%"=="bar1" if not "%foo2%"=="bar2" goto :another_menu

즉, foo1이 설정되지 않은 경우 foo2가 설정되지 않은 경우 goto :another_menu로 이동합니다.

또는 더 쉽게 foo1과 foo2가 설정되지 않은 경우 다른 메뉴로 이동합니다.

답변2

findstr을 사용하면 논리를 약간 단순화할 수 있습니다.

 Echo("%foo%"|Findstr /C:"bar1" /C:"bar2" > nul && Goto :FooBarMenu || Goto :AnotherMenu

논리: Findstr은 문자열을 %foo%bar1 및 bar2와 비교합니다. 일치하는 항목이 있으면 명령이 성공적으로 완료되고 조건부 연산자가 &&다음 명령을 실행합니다. 일치하는 항목이 없으면 ||이전 명령이 성공적으로 실행되지 않았으므로 조건부 연산자가 다음 명령을 실행하여 트리거됩니다.

예:

@Echo off
 Set "foo=notbar"

:loop
 Echo("%foo%"|Findstr /C:"bar1" /C:"bar2" > nul ^
 && Call :fooBarMenu foobarMenu || Call :AnotherMenu Anothermenu
 If not defined foo Exit /B 0
Goto :loop

:foobarmenu
 Echo(@ %~1 foo = %foo%
 Set "foo="
Exit /B 0

:Anothermenu
 Echo(@ %~1 foo = %foo%
 Set "foo=bar2"
Exit /B 0

답변3

bar1및 을(를 ) 이미 확인하셨습니다 bar2. 따라서 ISN이 bar1아닌지 다시 확인할 필요가 없습니다 bar2(코드 흐름이 이 지점에 도달했을 때 이미 다른 곳으로 분기했기 때문에 확실히 그렇지 않습니다).

rem Check if foo was previously set as bar1 or bar2...
if "%foo%"=="bar1" goto :foobar_menu
if "%foo%"=="bar2" goto :foobar_menu
rem no need to check if foo was NOT previously set as bar1 or bar2
rem if FOO is anything other than the previously checked values, 
rem your code will continue here anyway.
echo FOO isn't bar1 or bar2.
rem Don't forget to end this branch of your code or it will just continue to run:
goto :eof
:foobar_menu
echo reached foobar.

대문자를 무시하기 위해 /i스위치 사용을 고려할 수도 있습니다 ( is false, is true).if
if "foo"=="FOO"if /i "foo"=="FOO"

관련 정보