BrainStone
BrainStone

Reputation: 3195

Windows Batch check if variable starts with, ends with and contains a specific string

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

Answers (3)

dbenham
dbenham

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

Aacini
Aacini

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

Magoo
Magoo

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

Related Questions