Page 1 of 2

One-liners for logical OR operator

Posted: 21 Jun 2016 13:16
by sambul35
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)?

Re: One-liners for logical OR operator

Posted: 21 Jun 2016 13:52
by aGerman

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

Re: One-liners for logical OR operator

Posted: 21 Jun 2016 14:01
by sambul35
Thanks, its part of what I mean. I'll think of more example types... :)

Re: One-liners for logical OR operator

Posted: 21 Jun 2016 14:04
by penpen
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

Re: One-liners for logical OR operator

Posted: 21 Jun 2016 19:34
by sambul35
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!

Re: One-liners for logical OR operator

Posted: 21 Jun 2016 19:53
by sambul35
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:

Re: One-liners for logical OR operator

Posted: 22 Jun 2016 00:02
by Aacini
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

Re: One-liners for logical OR operator

Posted: 22 Jun 2016 01:56
by jeb
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

Re: One-liners for logical OR operator

Posted: 22 Jun 2016 09:54
by penpen
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

Re: One-liners for logical OR operator

Posted: 23 Jun 2016 09:42
by sambul35
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:

Re: One-liners for logical OR operator

Posted: 23 Jun 2016 11:17
by penpen
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

Re: One-liners for logical OR operator

Posted: 23 Jun 2016 13:07
by sambul35
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.

Re: One-liners for logical OR operator

Posted: 23 Jun 2016 13:51
by foxidrive
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."
:)

Re: One-liners for logical OR operator

Posted: 23 Jun 2016 15:45
by penpen
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).

Re: One-liners for logical OR operator

Posted: 24 Jun 2016 05:21
by sambul35
@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?