0

I'm trying to get a batch script to not accept quotation marks as acceptable variables.

For example:

:setmyvar
set /P myvariable=
if /i %myvariable%==<anything containing one or more "> goto bad
goto success

:bad
echo Variable cannot contain quotation marks.
pause
goto setmyvar

:success
echo Success!

So I basically, no matter what the variable is, if it has even one quotation mark (yes, even inside of a word like:

exa"mple

It will not accept it and prompt the user to enter something else.

Thank you

ditheredtransparency
  • 475
  • 3
  • 10
  • 18

2 Answers2

2

Following code could be used to check input of user:

@echo off
setlocal EnableExtensions EnableDelayedExpansion

:setmyvar
set "myvariable=""
set /P "myvariable=Please enter: "
set "TestVar=!myvariable:"=!"

if not defined TestVar goto setmyvar

if not "!TestVar!" == "!myvariable!" (
    echo/
    echo Variable cannot contain quotation marks.
    echo/
    pause
    echo/
    goto setmyvar
)

echo Success^^!
rem Other commands.
endlocal

Before prompting the user the environment variable myvariable is defined with a double quote. In case of user just hits RETURN or ENTER the environment variable myvariable keeps its current value (or is still not defined if not defined before).

After user prompt a new environment variable TestVar is defined with value of environment variable myvariable, but with all double quotes removed.

There are now three possibilities:

  1. TestVar is not defined at all now as the user did not enter anything or just double quotes.
  2. TestVar is different to myvariable as myvariable contains among other characters also 1 or more double quotes.
  3. TestVar is equal myvariable as the user entered a string which does not contain any double quote.

It is necessary for the comparison of not equal environment variables to use delayed expansion as otherwise with immediate environment variable expansion %myvariable% with double quotes would result in a syntax error.

In first case the user is simply prompted once again.

In second case the user is informed about the requirement to enter the string without quotation marks and then can enter the string once again whereby the user can use the UP ARROW to recall previous entered string and edit it.

And in third case the batch file execution continues.

The exclamation mark in text to output with echo must be escaped with two carets because of delayed expansion is still enabled as needed for the remaining code to access value of myvariable. After endlocal the environment variable myvariable does not exist anymore except the following command line is used:

endlocal & set "myvariable=%myvariable%"

This line would define myvariable in previous environment restored by command endlocal with current value of myvariable in active environment on parsing this command line.

echo/ just outputs a blank line in a more safer way than echo. does.

For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.

  • echo /?
  • endlocal /?
  • goto /?
  • if /?
  • rem /?
  • set /?
  • setlocal /?

For more help on what setlocal and endlocal do read this answer and the two other answers referenced there. For an explanation on using set "variable=value" see the answer on Why is no string output with 'echo %var%' after using 'set var = text' on command line?

Community
  • 1
  • 1
Mofi
  • 46,139
  • 17
  • 80
  • 143
  • Thank you so much for this! This helped a bunch! I was just struggling for a moment until I realized that it's mandatory for the "setlocal EnableExtensions EnableDelayedExpansion" to be at the top (or at least under echo off). Is it possible for me to turn this on & off anywhere in the script? – ditheredtransparency Feb 01 '17 at 08:30
  • Yes, of course as I wrote in the answer. In answer written by [MC ND](http://stackoverflow.com/users/2861476/mc-nd) delayed expansion is enabled to absolute minimum command block demonstrating what you are asking for, too. Command extensions as also enabled is by default enabled on Windows (except a registry value is modified) and is required here as otherwise `set /P` is not available. But that is also explained in detail in one of the referenced answers. – Mofi Feb 01 '17 at 10:19
2

Same approach to quote detection used in the Mofi`s answer (if the value in the variable does not change when quotes are removed then the variable does not contain quotes), code logic has been simplified and delayed expansion is only enabled if/when needed.

@echo off
    setlocal enableextensions disabledelayedexpansion

:input
    set /p "userInput=? " || (
        echo Error - Empty input not allowed
        goto :input
    )

    setlocal enabledelayedexpansion
    if not !userInput!==!userInput:^"=! set "userInput="
    endlocal & if "%userInput%"=="" (
        echo Error - Invalid input - quotes not allowed
        goto :input
    )

    Echo Ok - Successful input

If the user does not input anything, the set /p command fails and this failure is handled by the || conditional operator (execute next command if the previous one failed), requesting a new input.

Handling a string that can have special characters and unbalanced quotes can be problematic, but delayed expansion allows us to use the value in the variables after some of the more problematic parser phases have been executed. So, delayed expansion is enabled and using a string substitution operation (replace quotes with nothing) we check the value in the variable against the same value without quotes. If they don't match, we clean the variable.

After that, delayed expansion is not needed and is disabled. Doing it we lose the change (clean) made to the variable if it contained quotes, but as the line is parsed before being executed, using normal variable reference (%var%) and not delayed expansion reference (!var!) the read operation is replaced with the value in the variable before starting to execute the commands in the line, so, we can retrieved the changed value. If the variable is empty then it contained quotes and we should request a new value.

Community
  • 1
  • 1
MC ND
  • 69,615
  • 8
  • 84
  • 126