How to detect if input is quote?
Asked Answered
S

5

4

I have the following code

if "%userInput%"==""" (
    do_something
)

I would like it to detect if the %userInput% is a quote("). However, this code throws an error.

How to detect if input is a quote?

Serle answered 15/9, 2017 at 11:40 Comment(0)
M
5

Here is a solution without delayed expansion that should work with any input, including spaces and poison characters. My test code is in a loop. When you are ready to quit, simply press <Enter> without typing anything.

@echo off
setlocal

:loop
set "var="
set /p "var=enter a string: "
if not defined var exit /b

if "%var:"=""%" == """" echo equals quote

echo(
goto loop

The trick should be fairly obvious. Enclose the value in quotes, and double all internal quotes during expansion, such that all token delimiters and poison characters are guaranteed to be quoted. Of course on the right side you must include the enclosing quotes, plus the doubled quote you are trying to match (for a total of 4).

If you need to be able to pass all input (including no value) through the IF test, then you can define a test variable. Something like the following (assume var already has the user input)

set "test="
if defined var set "test=%var:"=""%"
if "%test%" == """" echo equals quote

Alternate solution using FINDSTR

I was inspired by Stephan's answer to find an alternative solution using FINDSTR that does not require delayed expansion. He interpreted the question differently, answering the question "Does the input value contain a quote anywhere within it?", and solved that using FIND.

But FIND cannot determine if the input exactly matches a single quote character.

A simple one liner with FINDSTR can solve this.

2>nul set var|findstr /x ^"var=\"" >nul && echo equals quote

or

2>nul set var|findstr /x "var=\"^" >nul && echo equals quote

Note that FINDSTR generally requires quotes to be escaped as \", and the batch parser requires one of the quotes to be escaped as ^" because there are an odd number of quotes. If a quote is not escaped, then the remainder of the line is considered to be part of the string instead of redirection and conditional execution operations.

Also note that with the batch parser, it is impossible to escape a quote once quoting is activated. So the following does NOT work

2>nul set var|findstr /x "var=\^"" >nul && echo equals quote THIS DOES NOT WORK
Maples answered 16/9, 2017 at 0:12 Comment(9)
When I remove the if not defined statement, the script still exit when I enter nothing, and throw an syntax error.Serle
Yes, You cannot execute my IF comparison if the variable is undefined because "%undefinedVar:"=""%" expands to ""="""Maples
Would this precaution work: setting the var to some sort of unused string so it should compare that string, not empty user input.Serle
I would create another test variable so that you don't disturb the original. I'll update my answerMaples
I tried your updated script, and it works perfectly good except exclamation marks get 'expanded' and become nothing. I have delayedExpansion off.Serle
That can't be. ! only gets "expanded" if delayed expansion is enabled. ! within input is preserved when I test my code with delayed expansion off.Maples
Maybe I wasn't clear. ! alone works as expected, but !" outputs equals quote.Serle
Not in my hands. You must have delayed expansion enabled. Double check your code. Perhaps you should explicitly disable delayed expansion within your code, just in case your command line has it enabled (this could happen inadvertently if a batch script crashes while SETLOCAL ENABLEDELAYEDEXPANSION is active).Maples
Let us continue this discussion in chat.Serle
C
6

as you asked "if input contains a quote". Just find it:

set "i=hello " world"
set i|find """" >nul && echo yes || echo no

Note: echo %i%|find """" may not work with unpaired quotes, but set doesn't care.

Note the """" syntax (looks strange and is unintuitive). find doesn't seem to use the usual escaping: find "^"" gives syntax error.

Comitia answered 15/9, 2017 at 13:2 Comment(4)
The """" syntax is really weird. But according to here, find do use the uncommon way of escaping.Serle
+1 Your interpretation is the most common interpretation of "contains a quote". But later on the OP asks "how to detect if input is quote?", which is entirely different. FIND cannot determine if input exactly matches a quote, but FINDSTR can. See my answerMaples
@Maples @Comitia Perhaps my post contains two different questions. Should I change "contains a quote" to "is a quote"?Serle
@SteveFest - Sure, "is a quote" or "equals a quote" would make the question clearer.Maples
M
5

Here is a solution without delayed expansion that should work with any input, including spaces and poison characters. My test code is in a loop. When you are ready to quit, simply press <Enter> without typing anything.

@echo off
setlocal

:loop
set "var="
set /p "var=enter a string: "
if not defined var exit /b

if "%var:"=""%" == """" echo equals quote

echo(
goto loop

The trick should be fairly obvious. Enclose the value in quotes, and double all internal quotes during expansion, such that all token delimiters and poison characters are guaranteed to be quoted. Of course on the right side you must include the enclosing quotes, plus the doubled quote you are trying to match (for a total of 4).

If you need to be able to pass all input (including no value) through the IF test, then you can define a test variable. Something like the following (assume var already has the user input)

set "test="
if defined var set "test=%var:"=""%"
if "%test%" == """" echo equals quote

Alternate solution using FINDSTR

I was inspired by Stephan's answer to find an alternative solution using FINDSTR that does not require delayed expansion. He interpreted the question differently, answering the question "Does the input value contain a quote anywhere within it?", and solved that using FIND.

But FIND cannot determine if the input exactly matches a single quote character.

A simple one liner with FINDSTR can solve this.

2>nul set var|findstr /x ^"var=\"" >nul && echo equals quote

or

2>nul set var|findstr /x "var=\"^" >nul && echo equals quote

Note that FINDSTR generally requires quotes to be escaped as \", and the batch parser requires one of the quotes to be escaped as ^" because there are an odd number of quotes. If a quote is not escaped, then the remainder of the line is considered to be part of the string instead of redirection and conditional execution operations.

Also note that with the batch parser, it is impossible to escape a quote once quoting is activated. So the following does NOT work

2>nul set var|findstr /x "var=\^"" >nul && echo equals quote THIS DOES NOT WORK
Maples answered 16/9, 2017 at 0:12 Comment(9)
When I remove the if not defined statement, the script still exit when I enter nothing, and throw an syntax error.Serle
Yes, You cannot execute my IF comparison if the variable is undefined because "%undefinedVar:"=""%" expands to ""="""Maples
Would this precaution work: setting the var to some sort of unused string so it should compare that string, not empty user input.Serle
I would create another test variable so that you don't disturb the original. I'll update my answerMaples
I tried your updated script, and it works perfectly good except exclamation marks get 'expanded' and become nothing. I have delayedExpansion off.Serle
That can't be. ! only gets "expanded" if delayed expansion is enabled. ! within input is preserved when I test my code with delayed expansion off.Maples
Maybe I wasn't clear. ! alone works as expected, but !" outputs equals quote.Serle
Not in my hands. You must have delayed expansion enabled. Double check your code. Perhaps you should explicitly disable delayed expansion within your code, just in case your command line has it enabled (this could happen inadvertently if a batch script crashes while SETLOCAL ENABLEDELAYEDEXPANSION is active).Maples
Let us continue this discussion in chat.Serle
L
3

with additional variable and delayed expansion:

@echo off

set /p quote=Enter quote
set "test_quote=""
setlocal enableDelayedExpansion

if !quote! equ !test_quote! echo equal
Levitan answered 15/9, 2017 at 11:47 Comment(2)
Ah! How did I forget delayed expansion when I use it on almost all my scripts :/Serle
No need for 2nd variable: if !quote! equ ^" echo equalMaples
F
2

…and possibly without delayed expansion:

@Echo Off
Set/P "input=Please input a character: "
If [^%input%]==[^"] (Echo it is a quote) Else Echo it is something else
Timeout -1
Flea answered 15/9, 2017 at 12:2 Comment(4)
if your input contains space the script will failLevitan
@Flea I once considered your method, but noticing that this will fail on input with space and special characters. Keyboard cats are everywhere.Serle
The question was about checking a quote as a single character, not a series of characters, you could for instance use If [^%input:~,1%]==[^"] to check a specific character. If the character is a space that could be catered for in a separate If, but is outside of the scope of the question. My answer was not given as a generic robust solution, just an alternative to show that enabling delayed expansion is not the only solution just the best one.Flea
@Flea Your last comment is correct indeed. I also understand the I asked for checking only 1 character. Your example is also a good one since it is delayed expansion free and doesn't have to worry about the input ! in other places of my script.Serle
P
0

Here is how I do it with enabledelayedexpansion

I am unsure if this would work without delayedexpansion

if "!_my_input_char!"==^"^"^" echo this was a doublequotes character

This appears to work correctly no matter what single character is inside of _my_input_char

Photon answered 7/7, 2023 at 6:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.