Skip to content

Instantly share code, notes, and snippets.

@davidruhmann
Last active October 13, 2015 16:48
Show Gist options
  • Save davidruhmann/4226276 to your computer and use it in GitHub Desktop.
Save davidruhmann/4226276 to your computer and use it in GitHub Desktop.
[Batch] Parse the command line parameters for easy consumption
:: Parse Example
:: Set a variable for each parameter flag to the value. flag:value, xflag=value
:: by David Ruhmann
:: Hide Commands
@echo off
:: Initilize Example
set "xParams=%*"
echo.%*
if not defined xParams (
rem How to use a symbol in [Command] [Command Quotes] [Batch] [Batch Quotes]
rem % = [%%] [%%] [^%%^%%^%%^%%] [%%%%%%%%]
rem ^ = [^^^^^^^^^^^^^^^^] [^^] [^^^^^^^^^^^^^^^^] [^]
rem CMD Example: -a:1 --b:\/2 /c:3 d -e:h%% --f:"h\/()= %%v^^l" /g: h: "-i:q"
call %0 -a:1 --b:\/2 /c:3 d -e:h^%%^%%^%%^%% --f:"h\/()= %%%%%%%%v^l" /g: h: "-i:q"
goto End
)
:: Parse the Command Line
call :Parse %*
:: View the Results
echo.Command Line:
set x
pause
:: Reset the variables
call :Parse -a --b /c d -e --f /g h -i
goto End
:End
:: by David Ruhmann
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:Parse
:: Parse the command line parameters in any sort order with no amount limit.
:: This sets a variable for each flag to the value. flag:value, xflag=value
:: Usage: call :Parse %* or call :Parse %1 %2 %3 %3 %4 %5 %6 %7 %8 %9
::
:: Unsupported Characters: !%^&()=|<> and some other rare symbol combinations.
:::: Note: characters ()= will work if they are contained within quotations.
:::: Note: character ! will work if delayed expansion is not enabled.
:::: Note: cmd.exe parameter delimiters: [space][tab],;=
:::: To use ^ or % escape them with themself ^^ %%. Quotations must be in pairs.
::
:: Reserved Characters: :; these can be changed.
:: Variable Prefix: x this can be changed.
::
:: DO NOT ISOLATE THE SCOPE. THE VALUES MUST BE SET IN THE CALLERS SCOPE.
:: Concatinate the param list with the ';' delimiter.
:::: Retrieve the first, shift, then concatinate each remaining param.
:::: Note added the escape escape ^^ since a single escape is misinterpreted.
set "xParams=%1"
shift
:NextParam
if (%1)==() goto StopParam
set "xParams=%xParams:^=^^%;%1"
shift
goto NextParam
:StopParam
:: Escape literal escapes to save them from being misinterpreted.
:::: This allows the no quote escapes to be ^^ not ^x16, but breaks quote escapes.
rem set "xParams=%xParams:^=^^^^^^%"
:: Convert into a string of echo commands
set "xParams=echo.%xParams:;=^&echo.%"
:: Loop through the strings printed by the echo commands
:::: Each echo is seens as a single loop; seperate each loop by the ':' delimiter
:::: into before:after x:y variables. Only surrounding quotes "x:y" are removed.
:::: The flags are made into variables prefixed with x and set to their y value.
for /f "usebackq delims=" %%a in (`%xParams%`) do (
for /f "usebackq tokens=1,2* delims=:" %%x in ('%%~a') do (
rem echo."%%x" = "%%y"
set "x%%x=%%y"
)
)
set "xParams="
goto :eof
:: by David Ruhmann
@echo off
call :Params /a /b c /d /e f "/g" "h i" /j:k "/l:m" /n:"o" /p:-q
set
pause
exit /b 0
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:: Parse parameters in "[/|-]flag[:| ][value]" format.
:: The param is set to null if there is no value.
:: WIP, Needs better efficiency and Need to allow negative numbers.
:: This is more work than its worth...
:: Currently Not Working...
:Params [/Param Value] ...
setlocal
set "P=%~1"
set V="%~2"
if defined P call :MatchOneOf "%P:~0,1%" "-/" || set "P="
if defined P for /f "tokens=1,* delims=:" %%A in ("%~1:") do set V="%%~B"
if defined V set "X=%V:"=%"
if defined X call :MatchOneOf "%V:~1,1%" "-/" && set "V="
if not defined X set "V="
if defined P set "P=%P:~1%"
endlocal & call :Expand "%P%" %V% null
call :Defined %3 || exit /b 0
shift
goto Params
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:: Parse parameters in "[/|-]flag value" format.
:: The param is set to null if there is no value.
:: WIP
:Params2 [/Param Value] ...
setlocal
set "P=%~1"
set V="%~2"
if defined P call :MatchOneOf "%P:~0,1%" "-/" || set "P="
if defined V call :MatchOneOf "%V:~1,1%" "-/" && set "V="
if defined P set "P=%P:~1%"
:: This will cause the last param to be skipped if there are an odd number.
::if defined V shift
endlocal & call :Expand "%P%" %V% null
call :Defined %3 || exit /b 0
shift
goto Params
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:: Parse parameters in "flag:value" format.
:Params1 [Param:Value] ...
for /f "tokens=1,* delims=:" %%A in ('%~1:') do call :Expand "%%~A" "%%~B"
call :Defined %2 || exit /b 0
shift
goto Params
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:: Match a single character to a list of possible characters.
:MatchOneOf <Char> <Chars>
for /f "delims=%~2" %%A in ("%~1") do exit /b 1
exit /b 0
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:: This works by exploiting the defined command. If the Var is null, then the
:: set command will fail, the error message is caught, and the defined command
:: will fail because there should NEVER exist a variable called exit.
:Expand <Var> [Value] [Default]
set "exit="
2>nul set "%~1=%~2"
if defined %~1 exit /b 0
exit /b 1
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:Defined <Input>
setlocal
set "Input=%~1"
if defined Input endlocal & exit /b 0
endlocal & exit /b 1
@echo off
:: Work In Progress
:: Extensions is Required to use "for /F"
:: Has yet to be tested for the following
:: Delayed Expansion Enabled
:: Delayed Expansion Disabled
:: Unicode
:: Special Characters
:: Escaped Characters
:: As of now the Value may not begin with a colon the delimiter
:: TODO
:: Keep parameters with no value
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:: Loads all parameters into variables specified by their flag. "flag:value key"
:: Do not use default environment variable names for flags or add a prefix. x%%A
:Params [%*]
if (%1)==() goto :eof
for /F "tokens=1,* delims=:" %%A in ("%~1:") do set "%%A=%%B"
shift
goto Params
:: by David Ruhmann
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:: Loads all parameters into variables specified by their flag. "flag:value key"
:: Do not use default environment variable names for flags or add a prefix. x%%A
:Params [%*]
setlocal EnableExtensions
set "xParam=%1"
if not defined xParam goto :eof
set "xParam=%xParam::= :%"
for /F "tokens=1,* delims=:" %%A in ("%~1:") do (
endlocal
set "%%A=%%B"
)
shift
goto Params
:: by David Ruhmann
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment