Hvordan får man valgfri kommandolinjeparameterværdi som en streng i Windows-batch script?

Indlæg af Hanne Mølgaard Plasc

Problem



Givet et valgfrit portargument, hvor portnummeret kan variere i længden, hvordan får jeg portnummeret fra batch scriptets kommandolinjeparametre?


Eksempel:


foo.bat --foo bar --port 80 --bar foo


Skal output:


80


Jeg har det her langt, forsøger at bruge substring.


set CMD\_LINE\_ARGS=\%*
@rem Remove all chars and port arg
set PORT\_ARG\_REMOVED=\%CMD\_LINE\_ARGS:*-port =\%
@rem Obviously, this is where I fail to remove trailing chars
set PORT\_NUM=\%PORT\_ARG\_REMOVED: *=\%
echo \%PORT\_NUM\%


Rediger


Svaret jeg valgte er, fordi det passer til mit meget særlige brugssag, hvor alle argumenter blev sendt videre til den kommando, jeg var indpakning. Og jeg havde kun brug for værdien for et bestemt valgfrit argument. Ingen looping kræves.


Der er nogle meget fine svar her for at håndtere valgfri argumentparsing generelt. Så vær så velkommen til at opvote alle.

Bedste reference


Se, som du 'virkelig ville have set at se substringsarbejdet', her er dit script struktureret og kodet som du havde tænkt dig.


@Set "CMD\_LINE\_ARGS=\%*"
@Rem Remove all chars and port arg
@Set "PORT\_ARG\_REMOVED=\%CMD\_LINE\_ARGS:*-port =\%"
@Rem Remove trailing chars
@Set "PORT\_NUM=\%PORT\_ARG\_REMOVED: ="&:"\%"
@Echo \%PORT\_NUM\%
@Pause

Andre referencer 1


Du kan bruge \%1, \%2 osv. Til de separate kommandolinjeparamenter. I dit tilfælde --port ville være \%3 og dets værdi ville være \%4.


Heldigvis er der også kommandoen shift, som skifter alle argumenter, til 2 bliver 1, 3 bliver 2 osv.


Det betyder at du kan 'skrabe' alle kommandolinjeparametre i en loop. Du fortsætter med at skifte, og når du støder på --port ved du, at den næste bliver portnummeret, som du kan gemme i en passende variabel (ved hjælp af set) til senere brug.


Hvis du implementerer det sådan, kan du implementere en flok valgfrie parametre, og ordren vinder heller ikke.


Så i kode kan din 'foo.bat' se sådan ud:


@echo off
:: No parameters given? Then run ourselves with the defaults from the question.
if "\%1"=="" goto none

:: Actual reading of parameters starts here.

:loop
if "\%1"=="--port" set port=\%2
:: Of course you need the other ifs only if you're interested in these parameters
if "\%1"=="--foo" set foo=\%2
if "\%1"=="--bar" set bar=\%2

:: Shift all parameters, except \%0. Do it twice to skip the parameter and its value.
shift /1
shift /1

:: As long as there are more, keep looping. You can even parse more than 10 parameters this way!
if not "\%1"=="" goto loop

:: Output what we've found
echo The specified port is \%port\%
echo Foo is set to \%foo\%
echo The bar is at \%bar\%
pause

exit /b

:: If no parameters are given, call ourselves with example parameters.
:none
call \%0 --foo bar --port 80 --bar foo


Udklædt version uden demo crap, der kun viser portnummeret. Jeg tror, ​​at dette er en erstatning for din nuværende kode.


@echo off
:loop
if "\%1"=="--port" set port=\%2
shift /1
shift /1
if not "\%1"=="" goto loop
echo \%port\%

Andre referencer 2


En enklere og åbenlyst tilgang, der får alle argumenter , betyder ikke noget, hvor mange:


@echo off
setlocal EnableDelayedExpansion

set "arg="
for \%\%a in (\%*) do (
   if not defined arg (
      set "arg=\%\%a"
   ) else (
      set "!arg:~2!=\%\%a"
      set "arg="
   )
)

echo foo = \%foo\%
echo port = \%port\%
echo bar = \%bar\%





Hvis du kan lide kort kode, gør versionen nedenfor den samme opgave i mindre linjer:


@echo off

set "args= \%*"
set "args=\%args: --=+\%"
set "args=\%args: ==\%"
set args=\%args:+=&set \%

echo foo = \%foo\%
echo port = \%port\%
echo bar = \%bar\%


Hvis du vil gennemgå, hvordan den kortere version fungerer, skal du blot fjerne linjen @echo off og udføre den.

Andre referencer 3




Jeg vil først fjerne --port -delen ved hjælp af substreng-udskiftning, og få værdien ved hjælp af en for /F sløjfe, som denne: [28] [29]


set CMD\_LINE\_ARGS=\%*
@rem Remove everything up to `--port` +  a space:
set "PORT\_ARG\_REMOVED=\%CMD\_LINE\_ARGS:*--port =\%"
@rem Extract first space- (or tab-)separated item:
for /F "tokens=1" \%\%A in ("\%PORT\_ARG\_REMOVED\%") do set "PORT\_NUM=\%\%A"
echo/\%PORT\_NUM\%


for /F -metoden har den store fordel, at den selv fungerer, når flere på hinanden følgende SPACE'er er givet for at adskille kommandolinjeparametrene.





Hvis du vil have koden til at tillade alle standardtegnskiltere (som er SPACE , TAB , ,, ;, = og tegn med kode 0xFF) i stedet for kun SPACE , kan du ændre koden til dette:


set "FLAG="
@rem Use a standard `for` loop to walk through the arguments:
for \%\%A in (\%*) do (
    @rem Capture the argument following the `--port` item:
    if defined FLAG if not defined PORT\_NUM set "PORT\_NUM=\%\%~A"
    @rem Use a `FLAG` variable to delay capturing argument by an iteration;
    @rem to match `--port` case-sensitively, remove the `/I` option:
    if /I "\%\%~A"=="--port" set "FLAG=#"
)
echo/\%PORT\_NUM\%


Faktisk foretrækker jeg på den måde, fordi der ikke er nogen strengmanipulation involveret, fordi listen over argumenter er analyseret i karakteren cmd.