批处理文件在 if 语句处不断崩溃

Posted

技术标签:

【中文标题】批处理文件在 if 语句处不断崩溃【英文标题】:Batch file keeps crashing at if statement 【发布时间】:2021-01-21 13:12:05 【问题描述】:

我正在制作一个简单的文字游戏。一切正常,直到它到达 if 语句。我不知道我做错了什么。

@echo off

title Text Adventures

echo "What is your name?"

set /p name=

echo "That was a bad crash. Are you hurt, %name%?"

echo.

echo Y/N

set /p answer=

if %answer% equ y goto hurt

:hurt

echo.

echo "I see. That's a gnarly gash you've got there!"

【问题讨论】:

您只能通过IF /I开关使用EQU和其他字符串比较 你应该修改你的SET /P命令来询问用户的问题,因为单独的回显是不必要的,因为SET /P允许这种形式SET /P "VARIABLE=Test to Display to User" 同样,我会使用 CHOICE 而不是 SET /P 进行选择,因为它很容易用于快速选择 1 个字母的回复 choice /? 给你一些例子。 see here 【参考方案1】:

在这里,我将其重写为使用函数的形式,并将我提供给原始帖子的建议用作 cmets。

您知道我错误地假设您使用标签是有目的的,但考虑到问题给出的方式,我认为您最好不要打扰它们。

这是一个无标签版本:

@(SETLOCAL
  echo off
  title Text Adventures
)

CALL :Main

( ENDLOCAL
 ECHO. The Script Ended!
 PAUSE
 EXIT /B
)

:Main

  set /p "name=What is Your Name?"
  ECHO.
  CHOICE /M "That was a bad crash. Are you hurt, %name%?"
  
  If %ERRORLEVEL% equ 1 (
    echo.
    echo "I see. That's a gnarly gash you've got there!"
  ) ELSE (
    echo.
    echo "Oh Good!"
  )
  PAUSE
GOTO :EOF

这是标签版本。 (我删除了解释它如何工作的 cmets 以及为什么代码在那里,所以它对你来说不会那么混乱。)

@(SETLOCAL
  echo off
  title Text Adventures
)

CALL :Main

( ENDLOCAL
 ECHO. The Script Ended!
 PAUSE
 EXIT /B
)

:Main

  set /p "name=What is Your Name?"
  ECHO.
  CHOICE /M "That was a bad crash. Are you hurt, %name%?"
  
  If %ERRORLEVEL% equ 1 (
    CALL :Hurt
  ) ELSE (
    CALL :NotHurt
  )
  PAUSE
GOTO :EOF

:Hurt
  echo.
  echo "I see. That's a gnarly gash you've got there!"
GOTO :EOF

:NotHurt
  echo.
  echo "Oh Good!"
GOTO :EOF

【讨论】:

我需要了解更多。但我确定它有效,所以检查它 你为什么要用函数来做你只做一次的事情? @SomethingDark 这对 OP 来说是一个更好的问题。 OP 只给出了一个 sn-p,如果他只需要编写这些行,那么他使用 GOTOs 到达的子函数似乎完全没有必要,除非他计划稍后对它们做更多。我只是让他怀疑他是否真的想在那里做一些更复杂的事情,并建议他CALLs 函数而不是GOTOs 给他们。 @JosephZamora So... not to be mean, but your answer sucks. i looked at it again and i just forgot to add pause at the end. you made it WAY too complicated. – Joseph Zamora yesterday 好吧,如果您不想刻薄,您可以很容易地将您的评论表述为不那么刻薄。实际上,我对你对帮助你的真诚努力缺乏感激之情感到相当惊讶和有点受伤。至于你对我帮助的看法,嗯,我猜有些人分不清好坏。 FWIW 我正在尝试对您的代码进行一些良好的实践,所以我想我可以以实物回应您的观点。 @JosephZamora 您会发现您现有的编码不允许您更改或重新使用您正在做的事情,我使用的表格将允许您创建模块并根据需要引用它们,并且是更干净,您的代码还使用了 GOTO 语句,除非有充分的理由使用它们,否则最好避免使用它们,这只是少数边缘情况,例如 GOTO :EOF ,它转到文件结尾参考,并允许您停止顺序执行并返回fa函数。【参考方案2】:

对于这类事情,我更喜欢使用选项,并且经常使用我的菜单宏,它将所选选项作为变量option中的字符串返回

下面是一个shell脚本,演示了我经常使用的几个宏的用法。

@ECHO Off & Goto :main
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:::                                           * Functions *                                      :::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:+------------------------------------------------------------------------------------------------+:
:ColorString
    (For %%C in (%~1)Do Set "rv=!rV!%/E%!#A!m%%~C%/E%0m"& Set /A "#A+=1"& IF "!#A!"=="37" (Set #A=31))
Exit /B 0
:+------------------------------------------------------------------------------------------------+:
:ColorMenu
rem  Set /A "RR=!random! %%195 + 60","GG=!random! %%195 + 60","BB=!random! %%195 + 60"
rem  Set "%~1=%/E%38;2;!RR!;!GG!;!BB!m!%~1!%/E%0m"
 Set "rV="& IF "!#A!"=="" (Set #A=32)
 (For %%C in ("!%~1!")Do Set "rv=!rV!%/E%!#A!m%%~C%/E%0m"& Set /A "#A+=1"& IF "!#A!"=="37" (Set #A=31)) & Set "%~1=!rV!"
Exit /B 0
:+------------------------------------------------------------------------------------------------+:
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:main                                  * Environment Definition *                                :::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
Rem /* ensure correct environment for macro definitions */
 Endlocal & Setlocal DISABLEdelayedexpansion
:+------------------------------------------------------------------------------------------------+:
 For /F %%a in ('echo prompt $E ^| cmd')do (Set "/E=%%a[")
:+------------------------------------------------------------------------------------------------+:
Set "ChoList=0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
 Set "ColLETTERS=Set "Rv="& Set "#A=31" & (For %%A in ("$Str")Do Set "Word=%%~A" & For %%B In (0 1 2 3 4 5 6 7 8 9 a b c d e f g h i j k l m n o p q r s t u v w x y z . + - _ [ ] / \ ":")Do Set "Word=!Word:%%~B=%%~B !") & (Call :ColorString "!Word!" & Echo/!rV!)"
 Set "ColWORD/S=Set "#A=35"& Set "MSG=$Str" & For %%G in ("!MSG!")Do (For %%v in (%%~G)Do (Set "Rv="&Call :Colorstring "%%~v"& For %%x in (!Rv!)Do (Set "MSG=!MSG:%%~v=%/E%0m%%~x!")))&Echo/!MSG!"
 Set "List/D/V=Set "#$L=0"&Set "$$L="&For %%n in (1 2)Do if %%n==2 (For %%G in (!$L!)Do (Set "%%~G" > Nul &Set /A "#$L+=1"))Else Set $L="
 Set "Menu=For %%n in (1 2)Do if %%n==2 (!DIV!&Set "CH#=0"&(Set "CHCS="&For %%G in (!Options!)Do For %%i in (!CH#!)Do (Set "CHCS=!CHCS!!ChoList:~%%i,1!"&Set "Opt[!ChoList:~%%i,1!]=%%~G"& Set "Opt=%%~G" &Call :ColorMenu Opt &<Nul Set /P "=[!ChoList:~%%i,1!] !Opt!"&Set /A "CH#+=1"&Echo/))&!DIV!& For /F "Delims=" %%o in ('Choice /N /C:!CHCS!')Do (Set "OPTION=!Opt[%%o]!"))Else Set Options="
 Set "ColLINE=For %%n in (1 2)Do if %%n==2 (Echo/!$C!!$Str!%/E%0m)Else Set $Str="
:+------------------------------------------------------------------------------------------------+:
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:::                                          * Script Body *                                     :::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
 Setlocal EnableDelayedExpansion
 for /F "usebackq tokens=2* delims=: " %%W in (`mode con ^| findstr Columns`) do Set "Console_Width=%%%W"
 Set "DIV="&For /L %%i in (2 1 %Console_Width%)Do Set "DIV=!DIV!-"
 Set "DIV=Echo/%/E%33m!DIV!%/E%0m"
 %List/D/V:$L=Colors%"Red=%/E%31m" "Yellow=%/E%33m" "Green=%/E%32m" "Blue=%/E%34m" "Purple=%/E%35m" "Cyan=%/E%36m" "White=%/E%37m" "Gray=%/E%90m" "Pink=%/E%91m" "Beige=%/E%93m" "Aqua=%/E%94m" "Magenta=%/E%95m" "Teal=%/E%96m" "Off=%/E%0m" "Black=%/E%30m"
 %List/D/V:$L=Actions%"Buy a house=Did you win the lotto" "Go for a drive=Start your engines" "Walk on the wild side=Get mauled by a lion" "Run a mile=Fit yet" "flee the realm=fall down a hole" "battle trolls=A losing battle" "puzzle a conundrum=Enigma's Stigmatised" "solve 42=life is meaningless"
 %ColLETTERS:$Str=Welcome.%
 %ColWORD/S:$Str=Hello there my friend^! How are you today.%
 %ColLINE:$C=Teal%What a world we live in^^!
 %Menu%"Buy a house" "Go for a drive" "Walk on the wild side" "Run a mile" "flee the realm" "battle trolls" "puzzle a conundrum" "solve 42"
  For %%G in ("!Option!")Do Echo/!%%~G!

菜单宏为它提供的每个参数构建一个选择列表,使用子字符串修改迭代一个 36 个字符的选择列表来构建最终选择选项 - 意味着支持 36 个菜单选项。

更新

添加了一个额外的示例来展示一种使用选择来显示输出或采取行动而无需条件测试的方法。使用List/D/V 宏定义选项的值,可以直接扩展选定的OPTION。在示例中,它只是显示输出,但是可以分配包含简单命令的值,例如 SetGotocall,以执行所选菜单选项的特定操作。

【讨论】:

【参考方案3】:

我忘了加暂停

@echo off

title Text Adventures

echo "What is your name?"

set /p name=

echo "That was a bad crash. Are you hurt, %name%?"

echo.

echo Y/N

set /p answer=

if %answer% equ y goto hurt

:hurt

echo.

echo "I see. That's a gnarly gash you've got there!"

pause

【讨论】:

以上是关于批处理文件在 if 语句处不断崩溃的主要内容,如果未能解决你的问题,请参考以下文章

WinSCP 命令中的批处理文件 IF 语句语法

使用 if 语句后跟调用似乎在批处理文件中不起作用

批处理文件 - IF 语句问题

批处理文件使用 if 语句忽略环境变量

批处理文件中的多行 IF 语句内的变量值未递增 [重复]

批处理文件 If 语句导致 CMD 关闭且不起作用