对转到标签(批处理文件)Windows 感到困惑

对转到标签(批处理文件)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

您的批处理文件从上到下执行。

在第二个示例中,即使设置了foo2foo1,它始终会转到:another_menu。批处理文件越过这两个语句的唯一方法是同时设置了foo1和。foo2

您实际上是在创建一个逻辑或情况。

如果 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 未设置,转到:another_menu

或者,更简单来说,如果 foo1 和 foo2 未设置,则转到 another_menu

答案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则无需再次检查(当代码流到达此点时,它肯定不是 或 ,因为当它到达时您已经分支到其他地方了)。bar1bar2

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开关来if忽略大写字母
if "foo"=="FOO"为假,if /i "foo"=="FOO"为真)

相关内容