One-liners for logical OR operator

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Message
Author
sambul35
Posts: 192
Joined: 18 Jan 2012 10:13

One-liners for logical OR operator

#1 Post by sambul35 » 21 Jun 2016 13:16

This page gives a sample of boolen test, aimed to check if for example a certain batch argument has a certain value:

Code: Select all

@echo off
set "cities=;York;London;Brussels;"
if "%cities:;%2;=%"=="%cities%" echo Going to wrong city?
exit /b

I wonder if a similar one-liner can be derived to check if any of several arguments (%1 %2 %3 %4) doesn't match its predefined value (5 r back No)?

aGerman
Expert
Posts: 4654
Joined: 22 Jan 2010 18:01
Location: Germany

Re: One-liners for logical OR operator

#2 Post by aGerman » 21 Jun 2016 13:52

Code: Select all

if "%1 %2 %3 %4" neq "5 r back No" ...

or

Code: Select all

if "%*" neq "5 r back No" ...


If that isn't what you're looking for you should provide more details.

Regards
aGerman

sambul35
Posts: 192
Joined: 18 Jan 2012 10:13

Re: One-liners for logical OR operator

#3 Post by sambul35 » 21 Jun 2016 14:01

Thanks, its part of what I mean. I'll think of more example types... :)

penpen
Expert
Posts: 1991
Joined: 23 Jun 2013 06:15
Location: Germany

Re: One-liners for logical OR operator

#4 Post by penpen » 21 Jun 2016 14:04

Offtopic:
The funny thing is that i expected the source to create an error!
But it works!
Nice find sambul35.

Probably not as you (sambul35) expected (you should use delayed expansion and replace the outer percentage characters with exclamation marks; i've also added a semicolon),
but it is the first time i saw three percentage characters in one variable working:

Code: Select all

:: test.bat
@echo off
setlocal enableDelayedExpansion
set "cities=;York;London;Brussels;%%1;%%2;%%3;"
echo %cities:;%2;=;%
echo !cities:;%2;=;!
endlocal
goto :eof

Code: Select all

Z:\>test.bat London London
;York;London;Brussels;%1;%3;
;York;Brussels;%1;%2;%3;
Why does this work?


penpen

sambul35
Posts: 192
Joined: 18 Jan 2012 10:13

Re: One-liners for logical OR operator

#5 Post by sambul35 » 21 Jun 2016 19:34

penpen wrote:Probably not as you (sambul35) expected

"Yes" to delayed expansion. But I meant a different use case, if I got your post correctly:

Code: Select all

@echo off
setlocal EnableDelayedExpansion
set "cities=;York;London;Brussels;"
if "!cities:;%2;=!"=="!cities!" (echo Going to a wrong city?
) else ( echo Nice trip!)
exit /b

:: launch the batch with arguments: test.bat York Berlin Chicago

:: Output to console
Going to a wrong city?

:: now relaunch the batch with arguments: test.bat Havana London Toronto

:: Output to console
Nice trip!
Last edited by sambul35 on 23 Jun 2016 13:09, edited 1 time in total.

sambul35
Posts: 192
Joined: 18 Jan 2012 10:13

Re: One-liners for logical OR operator

#6 Post by sambul35 » 21 Jun 2016 19:53

aGerman wrote:If that isn't what you're looking for you should provide more details.

My above code validates one argument at a time, and yours validates all at once, when each has only one allowed value. May I complicate things a bit? Is it possible to create a one-liner that can identify, which of the expected set of 4 arguments

a) aren't defined (i.e. have "" empty values)?
OR
b) an argument doesn't match its allowed choice out of 3 predefined values?

I'm just trying to figure out, what approach would provide a shortest code to validate a restricted set of batch arguments with multiple allowed choices for each. :wink:

Aacini
Expert
Posts: 1885
Joined: 06 Dec 2011 22:15
Location: México City, México
Contact:

Re: One-liners for logical OR operator

#7 Post by Aacini » 22 Jun 2016 00:02

sambul35 wrote:Is it possible to create a one-liner that can identify, which of the expected set of 4 arguments

a) aren't defined (i.e. have "" empty values)?
OR
b) an argument doesn't match its allowed choice out of 3 predefined values?

I'm just trying to figure out, what approach would provide a shortest code to validate a restricted set of batch arguments with multiple allowed choices for each. :wink:


Well, perhaps not a one-liner, but close:

EDIT: The original code did not check for empty arguments, this was fixed.

Code: Select all

@echo off
setlocal EnableDelayedExpansion

set "set[1]=/York/London/Brussels/"
set "set[2]=/Red/Blue/Green/"
set "set[3]=/Up/Down/Left/"
set "set[4]=/A/B/C/"

set "error="
for /L %%i in (1,1,4) do call set "arg=/%%%%i" & for /F %%a in ("!arg!") do if "!set[%%i]:%%a/=!" equ "!set[%%i]!" set "error=!error!, #%%i (!arg:~1!)"
if defined error echo Bad arguments: %error:~1% & goto :EOF
echo Arguments correct

Antonio
Last edited by Aacini on 24 Jun 2016 09:40, edited 3 times in total.

jeb
Expert
Posts: 1041
Joined: 30 Aug 2007 08:05
Location: Germany, Bochum

Re: One-liners for logical OR operator

#8 Post by jeb » 22 Jun 2016 01:56

Unbelievable :shock: :!:

penpen wrote:Probably not as you (sambul35) expected (you should use delayed expansion and replace the outer percentage characters with exclamation marks; i've also added a semicolon),
but it is the first time i saw three percentage characters in one variable working:


First I thought, that it's simple case where the parser rules can explain it. :)
But, I have to expand the percent/delayed expansion rules :!:

See New/unknown behaviour in percent/delayed expansion

penpen
Expert
Posts: 1991
Joined: 23 Jun 2013 06:15
Location: Germany

Re: One-liners for logical OR operator

#9 Post by penpen » 22 Jun 2016 09:54

I've played a little bit with multiple percentages/exclamationmarks in one single (delayed) expanded variable.

You could do something similar like aGerman:

Code: Select all

@echo off

:: test cases
if "%~1" == "testing" (
   cls
   call "%~f0" York 1 !
   call "%~f0" Yor B !
   call "%~f0" ork B !
   call "%~f0" London B !
   call "%~f0" Brussels B !
   call "%~f0" A B !
   call "%~f0" A B '
   call "%~f0" A B +
   call "%~f0" A B -
   call "%~f0" A B `
   call "%~f0" A B ~
   call "%~f0" A B (
   call "%~f0" A B ")"
   call "%~f0" A B [
   call "%~f0" A B ]
   call "%~f0" A B {
   call "%~f0" A B }
   call "%~f0" A B ","
   call "%~f0" A B ^"""
   call "%~f0" A B /
   call "%~f0" A B \
   call "%~f0" A B C
   call "%~f0" A B ""
   call "%~f0" A B
   call "%~f0"
   call "%~f0" A B "&"
   call "%~f0" A B "|"
   call "%~f0" A B "&&"
   call "%~f0" A B "||"
   "%~f0" A B ^^
)
echo "%~1" "%~2" "%~3"

setlocal enableExtensions enableDelayedExpansion

:: characters used for invalid and valid data (valid if it is contained in the associated set)
set "i=0"
set "v=1"

:: example sets
set "set[1]=;York;London;Brussels;"
set "set[2]=;1;2;3;"
set "set[3]=;;\;/;&;&&;|;||;(;);[;];{;};^^;^!;';+;-;,;`;~;^";"

:: debug output (showing the real unescaped data)
set set[

:: these two lines do the work
set "valid=;i:%i%!set[1]:*;%~1;==;;v:_!=;;i:%i%!set[2]:*;%~2;==;;v:_!=;;i:%i%!set[3]:*;%~3;==;;v:_!=;"
set "valid=%valid:;=!%"

:: debug output
echo(#!valid!#

if "!valid!" == "!v!!v!!v!" echo All arguments are valid.
endlocal
goto :eof
Xou have to be carefull, when using poisonous characters, but it is possible to use them.


penpen

sambul35
Posts: 192
Joined: 18 Jan 2012 10:13

Re: One-liners for logical OR operator

#10 Post by sambul35 » 23 Jun 2016 09:42

penpen wrote:I've played a little bit with multiple percentages/exclamationmarks in one single (delayed) expanded variable.

Thanks for your investigation into the above approach, initially suggesting using an expanded batch or function argument as a SEARCH pattern in REPLACE strings. I'm still grasping all possible practical implications aimed at shorter more efficient input validation and variable match analysis. :)

Aacini wrote:Well, perhaps not a one-liner, but close

Thanks Antonio! As always, unusual, non-standard, and very efficient. And it works! :D

I found one issue though in brief testing: the script seems to not distinguish btw Upper & Lower case letters in words, meaning "London" is processed the same as "london". Is it on purpose for making it more tolerant to user input errors? Can it be updated to account for Upper & Lower case? :wink:

penpen
Expert
Posts: 1991
Joined: 23 Jun 2013 06:15
Location: Germany

Re: One-liners for logical OR operator

#11 Post by penpen » 23 Jun 2016 11:17

The string replacement in variables doesn't differ between lower and upper case letters.
Your example in the opening post (or better its corrected version) also shows this behaviour.


penpen

sambul35
Posts: 192
Joined: 18 Jan 2012 10:13

Re: One-liners for logical OR operator

#12 Post by sambul35 » 23 Jun 2016 13:07

Good point, which might feel like a Cmd bug. However, my question in the 1st post was a bit broader ("No" argument was with capital N), and not necessarily limited to REPLACE expression. Generally it seems beneficial to figure out a way to account also for capital letters in a restricted set of several arguments (with each allowed fixed choice of values) when validating input, if at all possible in a short one-liner.

foxidrive
Expert
Posts: 6031
Joined: 10 Feb 2012 02:20

Re: One-liners for logical OR operator

#13 Post by foxidrive » 23 Jun 2016 13:51

sambul35 wrote:Good point, which might feel like a Cmd bug. However, my question in the 1st post was a bit broader ("No" argument was with capital N)

Just commenting that your question made no mention of case sensitivity and assuming aspects of a program is not something a programmer would do.

EDIT: My point here is that when reading a question we can't assume anything to write a program.

sambul35 wrote:Thanks Antonio! As always, unusual, non-standard, and very efficient. And it works! :D

I'd write that more simply: "As always, clever and very efficient."
:)

penpen
Expert
Posts: 1991
Joined: 23 Jun 2013 06:15
Location: Germany

Re: One-liners for logical OR operator

#14 Post by penpen » 23 Jun 2016 15:45

Then findstr.exe may be an option.

Code: Select all

@echo off
setlocal enableExtensions enableDelayedExpansion
set "set[1]=;York;London;Brussels;"
set "set[2]=;1;2;3;"
set "set[3]=;;\;/;&;&&;|;||;(;);[;];{;};^^;^!;';+;-;,;`;~;^";^";"

call
for /F "tokens=* delims=:" %%a in ('set set[ ^| findstr /V /N /B /R /C:"set\[1\].*;%~1;" /C:"set\[2\].*;%~2;" /C:"set\[3\].*;%~3;"') do call;
if errorlevel 1 echo All arguments valid.

endlocal


penpen

Edit: Fixed issues (missing delimiter and missing initial call).
Last edited by penpen on 24 Jun 2016 06:44, edited 1 time in total.

sambul35
Posts: 192
Joined: 18 Jan 2012 10:13

Re: One-liners for logical OR operator

#15 Post by sambul35 » 24 Jun 2016 05:21

@penpen

This one doesn't work for me in Win10, other than for the 3rd argument:

Code: Select all

c:\Tests>test.bat Paris
All arguments valid

c:\Tests>test.bat Paris 2 key

c:\Tests>


What "set\[1\].*%~1" and call; are expected to do, and why there is no output to screen from FINDSTR?

Post Reply