Reputation: 3195
I'm trying to check if a variable in a batch file starts with "
contains BETA
somewhere and ends with ")
.
Is it possible? And if yes, may somebody help me with that?
Upvotes: 9
Views: 31163
Reputation: 130849
Assuming your variable does not contain any line feeds or carriage returns, then all that is needed is a single FINDSTR command. It has limited regular expression support that is more than enough for this problem.
@echo off
setlocal
set test1=abc
set test2="abc"
set test3="")
set test4=")"
set test5=abc")"
set test6=xyzBETAzyx
set test7="xyz BETA zyx"
set test8=xyzBETAzyx")"
set test9=xyzBETAzyx")"
set test10="xyzbetazyx")
set test11="xyzBETAzyx")
for /l %%N in (1 1 11) do call :test test%%N
exit /b
:test variableName
setlocal enableDelayedExpansion
echo !%1!|>nul findstr /rx \".*BETA.*\") && set "result=PASS" || set "result=FAIL"
echo %1 = !result!: !%1!
exit /b
Only TEST11 passes.
The /R
option forces the search string to be treated as a regular expression.
The /X
option means it must be an exact match - the entire string must match the search string.
.*
is the regex wildcard expression that will match any string of characters.
I redirect the FINDSTR output to NUL because we don't need to see the line. We just want the return code
FINDSTR requires double quote literals to be escaped as \"
Use delayed expansion so that you can safely echo any value within the variable.
I use &&
to conditionally take action when FINDSTR succeeded, and ||
to conditionally take action when FINDSTR failed.
My :TEST
routine takes the name of the variable as the sole argument.
Note that in some situations, the batch parser requires that you also escape the double quote as ^"
, meaning a fully escaped quote will look like \^"
. But that complication is not needed in your case. The FINDSTR escape rules are actually a bit wonky. See What are the undocumented features and limitations of the Windows FINDSTR command? for more info.
My test code does a case sensitive search. So beta
will not match BETA
. If you want a case insensitive search, then simply add the /I
option.
EDIT: 2015-07-22
Another option, if and only if you want to ignore case, is to use a combination of variable expansion search/replace and expansion substring operations. Both test10 and test11 pass below.
@echo off
setlocal
set test1=abc
set test2="abc"
set test3="")
set test4=")"
set test5=abc")"
set test6=xyzBETAzyx
set test7="xyz BETA zyx"
set test8=xyzBETAzyx")"
set test9=xyzBETAzyx")"
set test10="xyzbetazyx")
set test11="xyzBETAzyx")
for /l %%N in (1 1 11) do call :test test%%N
exit /b
:test variableName
setlocal enableDelayedExpansion
set "result=FAIL"
if "!%1:beta=!" neq "!%1!" if "!%1:~0,1!" equ ^""" if "!%1:~-2!" equ ^"")" set "result=PASS"
echo %1 = !result!: !%1!
exit /b
The first IF checks for beta
anywhere (case insensitive). The second IF checks for "
at the beginning, and the last IF checks for ")
at the end. The only tricky thing is figuring out how to escape the comparison string when it has an odd number of quotes.
Upvotes: 11
Reputation: 67216
@echo off
setlocal EnableDelayedExpansion
set quote="
set variable="This must be true: BETA")
echo Variable=!variable!
if "!variable:~0,1!" equ "!quote!" (
rem Start with "
if "!variable:BETA=!" neq "!variable!" (
rem Contains BETA
if "!variable:~-2!" equ "!quote!^)" (
echo TRUE: it start with " contains BETA and ends with "^)
) else (
echo FALSE, it does not ends with "^)
)
) else (
echo FALSE, it does not contain BETA
)
) else (
echo FALSE, it does not start with "
)
Output:
Variable="This must be true: BETA")
TRUE: it start with " contains BETA and ends with ")
The way to deal with unbalanced quotes (and with other special Batch characters, indeed) is to use Delayed Expansion: this way the quotes and special characters don't appear in the command line being parsed.
Remember to escape with ^ any right parentheses that are not closing parentheses of command blocks.
An easy way to check if a variable contain a given string is try to eliminate the string from variable value: if the result is different to the original value, then the variable contain the string.
Antonio
Upvotes: 2
Reputation: 80033
@ECHO OFF
SETLOCAL
SET var=abc&CALL :check
SET var="abc"&CALL :llcheck
SET var="")&CALL :check
SET var=")"&CALL :llcheck
SET var=abc")"&CALL :llcheck
SET var=xyzbetazyx&CALL :check
SET var="xyzbetazyx"&CALL :llcheck
SET var=xyzbetazyx")"&CALL :llcheck
SET var=xyzbetazyx")"&CALL :check
SET var="xyzbetazyx")&CALL :check
GOTO :eof
:: Lop last, then check
:llcheck
SET var=%var:~0,-1%
:check
SET result=N
SET var2=%var%
SET varvar=%var%
>test1.txt ECHO %var:~0,1%%var:~-2%
>test2.txt ECHO "")
FC test1.txt test2.txt >nul
IF ERRORLEVEL 1 GOTO done
SET var|FINDSTR /b "var="|FINDSTR /i "beta" >nul
IF ERRORLEVEL 1 GOTO done
SET result=Y
:done
ECHO %var% starts " has BETA and ends ") : %result%
GOTO :eof
Where there's a will...
Setting variables with unbalanced "
can be tricky. I just set it up balanced and lopped off the last character (:llcheck
entry : lop last and check.
Essentiall, I've copied the variable into var2
and varvar
in oder to demo what happens should these variablenames be set.
Two files are then generated. TEST1.TXT
contains the first and last 2 character of var
and TEST2.TXT
simply "")
Compare the two - if they're not identical, then the variable does NOT start "
and end ")
Otherwise well - could simply have written var
out to a file and used findstr
to find beta
, but I decided to send the output of SET var
which should be the contents of ALL
of the var*
variables in the form
var=abc
var2=abc
varvar=abc
into findstr, finding the one that starts (/b
) var=
and finding whether THAT contains the string beta
The /i
selects case-insensitive. If you want specifically BETA
in UPPER-CASE, simply change beta
to BETA
and remove the /i
.
result
is set to Y
or N
Upvotes: 4