草庐IT

windows - Windows批处理if语句,带有用户输入

coder 2024-06-17 原文

.bat应该将用户输入与值进行比较。当我用输入1或2测试它时,它不会出现在IF "%choice%"=="1"中。

这是批处理文件:

@echo off
rem ...
IF [%$ecbId%] == [] (
    echo Enter '1' to blabla
    echo Enter '2' to blabla
    echo Enter anything to abort
    set /p choice="Type input: "
    IF "%choice%"=="1" (
        echo toto1
        rem save into property file
        echo currentMaster=%ecb%>> MDC.properties
        echo masterDcName=ECBDC>> MDC.properties
        echo currentClone=%bdf%>> MDC.properties
        echo cloneDcName=BDFDC>> MDC.properties
    )
    IF "%choice%"=="2" (
        echo toto2
        rem save into property file
        echo currentMaster=%bdf%>> MDC.properties
        echo masterDcName=BDFDC>> MDC.properties
        echo currentClone=%ecb%>> MDC.properties
        echo cloneDcName=ECBDC>> MDC.properties
    )
    IF NOT "%choice%"=="1" (
        echo toto3
        IF NOT "%choice%"=="2" (
            echo toto4
            echo Unknown input ... Aborting script
            exit /b 400
        )
    )
)

命令输出:
Enter '1' to blabla
Enter '2' to blabla
Enter anything to abort
Type input: 1
toto3
toto4
Unknown input ... Aborting script

为什么它不进入IF "%choice%"=="1"条件?

最佳答案

这是一个有效的批处理代码:

@echo off
setlocal EnableExtensions EnableDelayedExpansion
rem ...
if "%$ecbId%" == "" (
    echo Enter '1' to blabla
    echo Enter '2' to blabla
    echo Enter anything else to abort.
    echo/
    set "UserChoice=abort"
    set /P "UserChoice=Type input: "
    if "!UserChoice!" == "1" (
        echo toto1
        rem save into property file
        >>MDC.properties echo currentMaster=%ecb%
        >>MDC.properties echo masterDcName=ECBDC
        >>MDC.properties echo currentClone=%bdf%
        >>MDC.properties echo cloneDcName=BDFDC
    )
    if "!UserChoice!" == "2" (
        echo toto2
        rem save into property file
        >>MDC.properties echo currentMaster=%bdf%
        >>MDC.properties echo masterDcName=BDFDC
        >>MDC.properties echo currentClone=%ecb%
        >>MDC.propertiesecho cloneDcName=ECBDC
    )
    if not "!UserChoice!" == "1" (
        echo toto3
        if not "!UserChoice!" == "2" (
            echo toto4
            echo Unknown input ... Aborting script
            endlocal
            exit /B 400
        )
    )
)
endlocal

使用命令setlocal EnableExtensions EnableDelayedExpansion在批处理文件顶部启用Delayed expansion。命令 SETLOCAL 不仅启用延迟扩展,而且将整个命令过程环境保存在堆栈中,如我对change directory command cd ..not working in batch file after npm install的回答中详细解释的那样。在执行命令 ENDLOCAL 时,将从堆栈中还原命令处理环境,如果不显式执行endlocal,则退出退出批处理文件时,Windows命令处理器也将执行此操作。

在命令块中以(开头并以匹配的)结束并在同一命令块中引用的所有环境变量都必须使用延迟扩展进行引用。

当Windows命令处理器到达第四行时,整个命令块一直到最后,但是在 IF 条件被评估之前,对一行进行了解析和预处理。在该预处理步骤中,将用百分号引用的所有环境变量在整个块中从行4扩展到行36。

这意味着在对第4行上的 IF 条件进行求值之前,就像在 IF 条件本身中的%ecb%一样,对所有出现的%bdf%ecb都用环境变量bdf%$ecbId%的当前值替换。

在解析/预处理整个块时,不会仅扩展环境变量UserChoice,因为使用延迟扩展来引用此环境变量。

因此,可以为批处理用户仅按RETURN或ENTER而不输入任何内容的情况下为保留的环境变量abort分配诸如UserChoice之类的默认值。

由于在环境变量UserChoice中使用延迟扩展,因此用户输入的字符串不会在解析/预处理阶段扩展。在评估每个 IF 条件时,始终会解释UserChoice的当前字符串值。

Windows命令处理器的这种行为可以很容易地被观察到
  • 从批处理文件
  • 的第一行中删除@echo off
  • 打开命令提示符窗口
  • 如果当前目录不是批处理文件的目录,则在命令提示符窗口中运行的
  • 通过输入具有完整路径的批处理文件的名称来批处理文件。

  • 现在,Windows命令处理器始终在解析后始终在实际执行之前输出该行或命令块。因此可以看出,在达到的第一个条件时,整个命令块已经进行了预处理,将所有出现的%...%替换为来自环境变量的适当字符串,如果尚未定义引用环境变量,则什么也不会替换。可以看出,在Windows命令解释器执行整个命令块中的下一个命令行的同时,不再修改%ecb%%bdf%的值。

    更为紧凑的是:
    @echo off
    setlocal EnableExtensions EnableDelayedExpansion
    rem ...
    if "%$ecbId%" == "" (
        echo Enter '1' to blabla
        echo Enter '2' to blabla
        echo Enter anything else to abort.
        echo/
        set "UserChoice=abort"
        set /P "UserChoice=Type input: "
        if "!UserChoice!" == "1" (
            echo toto1
            rem save into property file
            >>MDC.properties echo currentMaster=%ecb%
            >>MDC.properties echo masterDcName=ECBDC
            >>MDC.properties echo currentClone=%bdf%
            >>MDC.properties echo cloneDcName=BDFDC
        ) else if "!UserChoice!" == "2" (
            echo toto2
            rem save into property file
            >>MDC.properties echo currentMaster=%bdf%
            >>MDC.properties echo masterDcName=BDFDC
            >>MDC.properties echo currentClone=%ecb%
            >>MDC.properties echo cloneDcName=ECBDC
        ) else (
            echo Unknown input ... Aborting script
            endlocal
            exit /B 400
        )
    )
    endlocal
    

    另一种解决方案是使用choice命令,该命令从Windows Vista开始默认可用。其优点是用户只需要按下三个键之一即可。在这种情况下,不需要延迟的环境变量扩展,因为choice会以取决于所按下键的值退出,该值取决于分配给环境变量errorlevel的值,即使在命令块中,也可以在不延迟扩展的情况下进行评估。
    @echo off
    rem ...
    if "%$ecbId%" == "" (
        echo Enter '1' to blabla
        echo Enter '2' to blabla
        echo Enter 'A' to abort.
        echo/
        %SystemRoot%\System32\choice.exe /C 12A /N /M "Type input:"
        if errorlevel 3 (
            echo Aborting script
            exit /B 400
        ) else if errorlevel 2 (
            echo toto2
            rem save into property file
            >>MDC.properties echo currentMaster=%bdf%
            >>MDC.properties echo masterDcName=BDFDC
            >>MDC.properties echo currentClone=%ecb%
            >>MDC.properties echo cloneDcName=ECBDC
        ) else (
            echo toto1
            rem save into property file
            >>MDC.properties echo currentMaster=%ecb%
            >>MDC.properties echo masterDcName=ECBDC
            >>MDC.properties echo currentClone=%bdf%
            >>MDC.properties echo cloneDcName=BDFDC
        )
    )
    

    用户必须按1导致choice1值退出,因为字符1被指定为选项/C之后的第一个字符,或者按下键2以使choice以值2退出,或者键A(不区分大小写)导致退出。在选项choice之后的下一个参数字符串中,将值为3作为字符A/C指定为第三个字符。附加确认后,可以另外按Ctrl + C组合键退出批处理文件。 choice会忽略所有其他按键操作,并会产生响铃噪音,以通知用户有关按键错误的信息。

    如今,最好将choice命令用于仅带有文件名或具有完整限定文件名的此类用户提示,以最大程度地确保执行安全。

    关于windows - Windows批处理if语句,带有用户输入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39276105/

    有关windows - Windows批处理if语句,带有用户输入的更多相关文章

    1. ruby - 在 Ruby 程序执行时阻止 Windows 7 PC 进入休眠状态 - 2

      我需要在客户计算机上运行Ruby应用程序。通常需要几天才能完成(复制大备份文件)。问题是如果启用sleep,它会中断应用程序。否则,计算机将持续运行数周,直到我下次访问为止。有什么方法可以防止执行期间休眠并让Windows在执行后休眠吗?欢迎任何疯狂的想法;-) 最佳答案 Here建议使用SetThreadExecutionStateWinAPI函数,使应用程序能够通知系统它正在使用中,从而防止系统在应用程序运行时进入休眠状态或关闭显示。像这样的东西:require'Win32API'ES_AWAYMODE_REQUIRED=0x0

    2. ruby - 如何指定 Rack 处理程序 - 2

      Rackup通过Rack的默认处理程序成功运行任何Rack应用程序。例如:classRackAppdefcall(environment)['200',{'Content-Type'=>'text/html'},["Helloworld"]]endendrunRackApp.new但是当最后一行更改为使用Rack的内置CGI处理程序时,rackup给出“NoMethodErrorat/undefinedmethod`call'fornil:NilClass”:Rack::Handler::CGI.runRackApp.newRack的其他内置处理程序也提出了同样的反对意见。例如Rack

    3. ruby-on-rails - 使用 rails 4 设计而不更新用户 - 2

      我将应用程序升级到Rails4,一切正常。我可以登录并转到我的编辑页面。也更新了观点。使用标准View时,用户会更新。但是当我添加例如字段:name时,它​​不会在表单中更新。使用devise3.1.1和gem'protected_attributes'我需要在设备或数据库上运行某种更新命令吗?我也搜索过这个地方,找到了许多不同的解决方案,但没有一个会更新我的用户字段。我没有添加任何自定义字段。 最佳答案 如果您想允许额外的参数,您可以在ApplicationController中使用beforefilter,因为Rails4将参数

    4. ruby-on-rails - `a ||= b` 和 `a = b if a.nil 之间的区别? - 2

      我正在检查一个Rails项目。在ERubyHTML模板页面上,我看到了这样几行:我不明白为什么不这样写:在这种情况下,||=和ifnil?有什么区别? 最佳答案 在这种特殊情况下没有区别,但可能是出于习惯。每当我看到nil?被使用时,它几乎总是使用不当。在Ruby中,很少有东西在逻辑上是假的,只有文字false和nil是。这意味着像if(!x.nil?)这样的代码几乎总是更好地表示为if(x)除非期望x可能是文字false。我会将其切换为||=false,因为它具有相同的结果,但这在很大程度上取决于偏好。唯一的缺点是赋值会在每次运行

    5. ruby - 在 Windows 机器上使用 Ruby 进行开发是否会适得其反? - 2

      这似乎非常适得其反,因为太多的gem会在window上破裂。我一直在处理很多mysql和ruby​​-mysqlgem问题(gem本身发生段错误,一个名为UnixSocket的类显然在Windows机器上不能正常工作,等等)。我只是在浪费时间吗?我应该转向不同的脚本语言吗? 最佳答案 我在Windows上使用Ruby的经验很少,但是当我开始使用Ruby时,我是在Windows上,我的总体印象是它不是Windows原生系统。因此,在主要使用Windows多年之后,开始使用Ruby促使我切换回原来的系统Unix,这次是Linux。Rub

    6. ruby - ruby 中有 each_if 吗? - 2

      假设我在Ruby中有这个each循环。@list.each{|i|putsiifi>10breakend}我想循环遍历列表直到满足条件。这让我感到“不像Ruby”,因为我是Ruby的新手,是否有Ruby方法可以做到这一点? 最佳答案 您可以使用Enumerable#detect或Enumerable#take_while,取决于您想要的结果。@list.detect{|i|putsii>10}#Returnsthefirstelementgreaterthan10,ornil.正如其他人所指出的,更好的风格是先进行子选择,然后再对其

    7. ruby-on-rails - 简单的 Ruby on Rails 问题——如何将评论附加到用户和文章? - 2

      我意识到这可能是一个非常基本的问题,但我现在已经花了几天时间回过头来解决这个问题,但出于某种原因,Google就是没有帮助我。(我认为部分问题在于我是一个初学者,我不知道该问什么......)我也看过O'Reilly的RubyCookbook和RailsAPI,但我仍然停留在这个问题上.我找到了一些关于多态关系的信息,但它似乎不是我需要的(尽管如果我错了请告诉我)。我正在尝试调整MichaelHartl'stutorial创建一个包含用户、文章和评论的博客应用程序(不使用脚手架)。我希望评论既属于用户又属于文章。我的主要问题是:我不知道如何将当前文章的ID放入评论Controller。

    8. ruby - 如何在 Ruby 中向现有方法定义添加语句 - 2

      我注意到类定义,如果我打开classMyClass,并在不覆盖的情况下添加一些东西我仍然得到了之前定义的原始方法。添加的新语句扩充了现有语句。但是对于方法定义,我仍然想要与类定义相同的行为,但是当我打开defmy_method时似乎,def中的现有语句和end被覆盖了,我需要重写一遍。那么有什么方法可以使方法定义的行为与定义相同,类似于super,但不一定是子类? 最佳答案 我想您正在寻找alias_method:classAalias_method:old_func,:funcdeffuncold_func#similartoca

    9. ruby - RVM "ERROR: Unable to checkout branch ."单用户 - 2

      我在新的Debian6VirtualBoxVM上安装RVM时遇到问题。我已经安装了所有需要的包并使用下载了安装脚本(curl-shttps://rvm.beginrescueend.com/install/rvm)>rvm,但以单个用户身份运行时bashrvm我收到以下错误消息:ERROR:Unabletocheckoutbranch.安装在这里停止,并且(据我所知)没有安装RVM的任何文件。如果我以root身份运行脚本(对于多用户安装),我会收到另一条消息:Successfullycheckedoutbranch''安装程序继续并指示成功,但未添加.rvm目录,甚至在修改我的.bas

    10. Vscode+Cmake配置并运行opencv环境(Windows和Ubuntu大同小异) - 2

      之前在培训新生的时候,windows环境下配置opencv环境一直教的都是网上主流的vsstudio配置属性表,但是这个似乎对新生来说难度略高(虽然个人觉得完全是他们自己的问题),加之暑假之后对cmake实在是爱不释手,且这样配置确实十分简单(其实都不需要配置),故斗胆妄言vscode下配置CV之法。其实极为简单,图比较多所以很长。如果你看此文还配不好,你应该思考一下是不是自己的问题。闲话少说,直接开始。0.CMkae简介有的人到大二了都不知道cmake是什么,我不说是谁。CMake是一个开源免费并且跨平台的构建工具,可以用简单的语句来描述所有平台的编译过程。它能够根据当前所在平台输出对应的m

    随机推荐