Confundido acerca de la etiqueta Ir a (archivo por lotes) Windows

Confundido acerca de la etiqueta Ir a (archivo por lotes) Windows

Si uso estos comandos de esta manera, hace lo que debería:

Sifoo erapreviamente configurado como una cosa u otra, salta afoobar_menu

si foofue anteriormentenoestablecido como (lo mismo) una cosa u otra, salta aanother_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

He aquí por qué me confunde: si los cambio como se muestra a continuación, entonces no funciona correctamente, va a la etiqueta incorrecta, pero ¿por qué?

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

¿Por qué estas dos cosas no hacen lo mismo?

¿Esto se debe a que no voy a poner las partes entre paréntesis?

Lo tengo funcionando (la primera forma), pero ese no es el mismo orden en el que van mis menús y solo quería que todo funcionara como está establecido en el segundo ejemplo (que no funciona) anterior.

Salud.

EDITAR:

Estos son los comandos reales. Cuando se expresa de esta manera, aunque está anidado, todavía irá a la etiqueta choose_audio_sample_rateaunque opus o libopus estén configurados debajo de la variable.

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

De hecho, la versión intercambiada tampoco funciona, también funciona choose_audio_sample_rateaunque opus o libopus estén configurados bajo la variable.

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

Me estoy volviendo un lunático aquí jajaja, está bien, simplemente funcionará (y pasará directamente al menú que no es opus) si solo uso esto:

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

Si es libopus, va a la etiqueta correcta. Si no es libopus, se procesa la siguiente línea y si es opus, va a la etiqueta correcta.

Si fue más allá, tampoco fue libopus ni opus y pasa al menú general.

Respuesta1

Su archivo por lotes se ejecuta de arriba hacia abajo.

En el segundo ejemplo, incluso si se establece foo2o foo1, siempre irá a :another_menu. La única forma en que el archivo por lotes pasará de esas dos declaraciones es si ambas foo1y foo2están configuradas.

Básicamente, estás creando una situación OR lógica.

Si foo1 O foo2 no están configurados, vaya a otro menú

DEMÁS

Si foo1 O foo2 están configurados, vaya a foobar_menu

DEMÁS

Hacer nada

Mientras que el primer ejemplo,

Si foo1 O foo2 están configurados, vaya a foobar_menu

DEMÁS

Si foo1 O foo2 no están configurados, vaya a otro menú

DEMÁS

Hacer nada

Lo que necesitas es específicamente un AND lógico. Las declaraciones IF del archivo por lotes no admiten ni AND ni OR. Entonces, los anidamos o los encadenamos así:

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

Esto dice: Si foo1 no está configurado, entonces si foo2 no está configurado, vaya a: otro_menu

O, más fácilmente, si foo1 Y foo2 no están configurados, vaya a otro_menú

Respuesta2

Su lógica se puede simplificar un poco mediante el uso de findtr

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

La lógica: Findstr compara la cadena %foo%con bar1 y bar2. Si hay una coincidencia, el comando se completa correctamente y el operador condicional &&ejecuta el siguiente comando. Si no hay coincidencia, ||el operador condicional se activa al ejecutar el siguiente comando, ya que el comando anterior no se ejecutó correctamente.

Ejemplo:

@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

Respuesta3

Ya verificaste bar1y bar2. Por lo tanto, no es necesario volver a verificar si NO LO ES bar1o bar2(definitivamente no lo es cuando el flujo de código llega a este punto porque ya se ramificó en otra parte cuando lo hizo).

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.

Quizás quieras considerar usar el /iinterruptor con ifpara ignorar las mayúsculas
( if "foo"=="FOO"es falso, if /i "foo"=="FOO"es verdadero)

información relacionada