Safe number comparison in Windows batch file

后端 未结 2 476
小蘑菇
小蘑菇 2020-12-21 04:31

I know that when comparing stuff for equality in a batch file it\'s common to enclose both sides in quotes, like

IF \"%myvar% NEQ \"0\" 

Bu

2条回答
  •  盖世英雄少女心
    2020-12-21 05:01

    Answering the call to nitpick

    Mofi has been requesting I write my own solution here, that is "shorter" as I pointed out to him the way he wrote his code using & instead of ( followed by a command then a carriage return and another command, or `( followed by a carriage return, followed by another command followed by a carriage return followed by another command) sets a precedent which makes this a hard task to agree on.

    I also did not think this was the POINT of providing the answers perse, I mean I used to, but when changes are minor, and mainly fixing logic, or offering a minorly different solution, is that really a big difference? Does that really warrant being a separate answer?

    That said, I don't see a better way without editing his response.. but this still leaves unresolved questions on what is being judged shorter.

    Unfortunately as well, in discussing with Mofi he has edited his answer to one that can result in invalid choices.

    While I have pointed this out, and I'm sure this was just a minor oversite on his part, I feel like not posting the code here has contributed to him actively deteriorating the quality of his question, which is always a possible outcome when nitpicking.

    while Mofi was the driving force in that activity, I don't like the effect it's had on him as I was trying to avoid exactly this effect on my code by not getting into it, so I have decided to post the code comparison to bring some closure for them.

    Please not, I will post his original code (the most recent one that did not use the erroneous method), and then refactored to how I would write it, and I will post my Original code, and then refactored to how I believe he would write it (may not be in that order but I will call out each)

    So below is the result

    Mofi Original:

    This is hard to say if you should count every line, there are some instances where & is used to queue up commands and the IFS never use Parenthesis which I wouldn't generally do.

    @echo off
    set "MinValue=0"
    set "MaxValue=20000"
    
    :PromptUser
    rem Undefine environment variable MyVar in case of being already defined by chance.
    set "MyVar="
    rem Prompt user for a positive number in range %MinValue% to %MaxValue%.
    set /P "MyVar=Enter number [%MinValue%,%MaxValue%]: "
    
    if not defined MyVar goto PromptUser
    setlocal EnableDelayedExpansion
    set /A "Number=MyVar" 2>nul
    if not "!Number!" == "!MyVar!" endlocal & goto PromptUser
    endlocal
    if %MyVar% GTR %MaxValue% goto PromptUser
    if %MyVar% LSS %MinValue% goto PromptUser
    
    rem Output value of environment variable MyVar for visual verification.
    set MyVar
    pause
    

    My Code Refactored to Mofi's Form

    @ECHO OFF
    SETLOCAL EnableDelayedExpansion
    SET /A "_Min=-1","_Max=20000"
    :Menu
      CLS
      SET "_Input="
      REM Prompt user for a positive number in range %_Min% to %_Max%.
      SET /P "_Input=Enter number [%_Min%,%_Max%]: "
      SET /A "_Tmp=%_input%" && if /I "!_input!" EQU "!_Tmp!" if !_Input! GEQ %_Min% if !_Input! LEQ %_Max% SET _Input & pause & GOTO :EOF 
    GOTO :Menu
    

    Mofi's Code Refactored

    Mofi's above code Refactored to my more compacted form Where ( have the first command follow except when used on an IF statement, and ) follow the last command. This also makes the entire portion that really does the validation EASY to discern, it is only the portion within the :PromtUser function, not counting REM lines or blank lines this is 13 lines of code.

    @(SETLOCAL
      echo off
      SET /A "MinValue=0","MaxValue=20000")
    
    CALL :Main
    
    ( ENDLOCAL
      EXIT /B )
    
    :Main
      CALL :PromptUser MyVar
      REM Output value of environment variable MyVar for visual verIFication.
      SET MyVar
      PAUSE
    GOTO :EOF
    
    
    :PromptUser
      SET "MyVar="
      rem Prompt user for a positive number in range %MinValue% to %MaxValue%.
      SET /P "MyVar=Enter number [%MinValue%,%MaxValue%]: "
      
      IF NOT DEFINED MyVar GOTO :PromptUser
      Setlocal EnableDelayedExpansion
      SET /A "Number=MyVar" 2>nul
      
      IF not "!Number!" == "!MyVar!" (
        Endlocal
        GOTO :PromptUser  )
      Endlocal
      IF %MyVar% GTR %MaxValue% (
        GOTO :PromptUser  )
      IF %MyVar% LSS %MinValue% (
        GOTO :PromptUser )
    GOTO :EOF
    

    My Code in My Compact Form

    To compare here is my code also in the same compact form I refactored Mofi's code to above. Again, only the lines inside of the function itself are "doing the heavy lifting" here and need compare. I did forget that when I worked on my code originally I was trying to match Mofi's form, and it allowed me an extra nicety in keeping my && ( in the following line or all as a single line. So I will post two varients

    @(SETLOCAL ENABLEDELAYEDEXPANSION
      ECHO OFF
      SET /A "_Min=-1","_Max=20000" )
    
    CALL :Main
    
    ( ENDLOCAL
      EXIT /B )
    
    :Main
      CALL :Menu _input
      REM Output value of environment variable _input for visual verIFication.
      SET _input
      PAUSE
    GOTO :EOF
    
    
    :Menu
      CLS
      SET "_input="
      REM Prompt user for a positive number in range %_Min% to %_Max%. Store it in "_input"
      SET /P "_Input=Enter number [%_Min%,%_Max%]: "
      SET /A "_Tmp=%_input%" && (
        IF /I "!_input!" EQU "!_Tmp!" IF !_Input! GEQ %_Min% IF !_Input! LEQ %_Max% GOTO :EOF )
    GOTO :Menu
    

    My Code in My Compact Form 2

    @(SETLOCAL ENABLEDELAYEDEXPANSION
      ECHO OFF
      SET /A "_Min=-1","_Max=20000" )
    
    CALL :Main
    
    ( ENDLOCAL
      EXIT /B )
    
    :Main
      CALL :Menu
      REM Output value of environment variable _input for visual verification.
      SET _input
      PAUSE
    GOTO :EOF
    
    
    :Menu
      CLS
      SET "_input="
      REM Prompt user for a positive number in range %_Min% to %_Max%. Store it in "_input"
      SET /P "_Input=Enter number [%_Min%,%_Max%]: "
      SET /A "_Tmp=%_input%" || GOTO :Menu 
      IF /I "!_input!" EQU "!_Tmp!" (
        IF !_Input! GEQ %_Min% (
          IF !_Input! LEQ %_Max% (
            GOTO :EOF ) ) )
    GOTO :Menu
    

提交回复
热议问题