Pliki wsadowe-ilość argumentów wiersza poleceń

Po prostu konwertuję niektóre skrypty powłoki do plików wsadowych i jest jedna rzecz, której nie mogę znaleźć...i to jest prosta liczba argumentów wiersza poleceń.

Np. jeśli masz:

myapp foo bar

W Powłoce:

  • $# -> 2
  • $ * - > Foo bar
  • $0 - > myapp
  • $1 - > foo
  • $2 - > bar
Nr serii

]}

  • ?? - >2
  • % * - > Foo bar
  • %0 - > myapp
  • %1 -> foo
  • %2 - > bar

Więc rozejrzałem się dookoła i albo patrzę w złe miejsce, albo jestem ślepy, ale nie mogę znaleźć sposobu, aby uzyskać liczbę argumentów linii poleceń przekazanych.

Czy istnieje polecenie podobne do polecenia shella "$ # " dla plików wsadowych?

Ps. najbliższe, jakie znalazłem, to iteracja przez %1s i użycie 'shift' , ale muszę referować %1,%2 itd. później w skrypcie, więc nie jest to dobre.

Author: Eric, 2009-08-18

7 answers

Trochę googlowania daje następujący wynik z wikibooks :

set argC=0
for %%x in (%*) do Set /A argC+=1

echo %argC%
Wygląda na cmd.exe wyewoluowało trochę ze starych czasów DOS:)
 85
Author: nimrodm,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-08-18 06:16:11

Masz tendencję do obsługi wielu argumentów za pomocą tego rodzaju logiki:

IF "%1"=="" GOTO HAVE_0
IF "%2"=="" GOTO HAVE_1
IF "%3"=="" GOTO HAVE_2

Itd.

Jeśli masz więcej niż 9 argumentów, to masz przesrane z tym podejściem. Istnieją różne hacki do tworzenia liczników, które można znaleźć tutaj, ale ostrzegam, że nie są one dla słabych serc.

 34
Author: Dean Povey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-27 16:39:23

Funkcja :getargc poniżej może być tym, czego szukasz.

@echo off
setlocal enableextensions enabledelayedexpansion
call :getargc argc %*
echo Count is %argc%
echo Args are %*
endlocal
goto :eof

:getargc
    set getargc_v0=%1
    set /a "%getargc_v0% = 0"
:getargc_l0
    if not x%2x==xx (
        shift
        set /a "%getargc_v0% = %getargc_v0% + 1"
        goto :getargc_l0
    )
    set getargc_v0=
    goto :eof

To w zasadzie iteruje raz nad listą (która jest lokalna dla funkcji, więc zmiany nie będą miały wpływu na listę z powrotem w głównym programie), licząc je, aż skończy się.

Używa również sprytnej sztuczki, przekazując nazwę zmiennej zwrotnej, która ma być ustawiona przez funkcję.

Główny program ilustruje tylko, jak go wywołać, a następnie odczytuje argumenty, aby upewnić się, że są nietknięte:

C:\Here> xx.cmd 1 2 3 4 5
    Count is 5
    Args are 1 2 3 4 5
C:\Here> xx.cmd 1 2 3 4 5 6 7 8 9 10 11
    Count is 11
    Args are 1 2 3 4 5 6 7 8 9 10 11
C:\Here> xx.cmd 1
    Count is 1
    Args are 1
C:\Here> xx.cmd
    Count is 0
    Args are
C:\Here> xx.cmd 1 2 "3 4 5"
    Count is 3
    Args are 1 2 "3 4 5"
 18
Author: paxdiablo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-08-18 06:18:16

Spróbuj tego:

SET /A ARGS_COUNT=0    
FOR %%A in (%*) DO SET /A ARGS_COUNT+=1    
ECHO %ARGS_COUNT%
 6
Author: David,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-04-05 20:20:45

Jeśli liczba argumentów powinna być dokładną liczbą (mniejszą lub równą 9), to jest to prosty sposób na sprawdzenie:

if "%2" == "" goto args_count_wrong
if "%3" == "" goto args_count_ok

:args_count_wrong
echo I need exactly two command line arguments
exit /b 1

:args_count_ok
 5
Author: slu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-15 13:15:49

Unika używania cyklu shift lub for kosztem rozmiaru i czytelności.

@echo off
setlocal EnableExtensions EnableDelayedExpansion
set /a arg_idx=1
set "curr_arg_value="
:loop1
if !arg_idx! GTR 9 goto :done
set curr_arg_label=%%!arg_idx!
call :get_value curr_arg_value !curr_arg_label!
if defined curr_arg_value (
  echo/!curr_arg_label!: !curr_arg_value!
  set /a arg_idx+=1
  goto :loop1
)
:done
set /a cnt=!arg_idx!-1
echo/argument count: !cnt!
endlocal
goto :eof

:get_value
(
  set %1=%2
)

Wyjście:

count_cmdline_args.bat testing more_testing arg3 another_arg

%1: testing
%2: more_testing
%3: arg3
%4: another_arg
argument count: 4

EDIT: użyty tu "trik" polega na:

  1. Konstruowanie łańcucha, który reprezentuje aktualnie ocenianą zmienną argumentu wiersza poleceń (np. "%1", "%2 " itd.) za pomocą ciągu zawierającego znak procentowy (%%) i zmienną licznika arg_idx na każdej iteracji pętli.

  2. Zapisanie tego ciągu do zmiennej curr_arg_label.

  3. Przekazując zarówno ten łańcuch (!curr_arg_label!), jak i zwracaną nazwę zmiennej (curr_arg_value) do prymitywnego podprogramu get_value.

  4. W podprogramie jego wartość pierwszego argumentu (%1) jest używana po lewej stronie przypisania (set), a wartość drugiego argumentu (%2) po prawej. Jednakże, gdy przekazywany jest argument drugiego podprogramu, jest on rozdzielany na wartość argumentu wiersza poleceń głównego programu przez interpreter poleceń. Czyli to, co jest przekazywane jest nie, na przykład, "%4", ale jaką wartość posiada czwarta zmienna argumentu wiersza poleceń ("another_arg" w przykładowym użyciu).

  5. Następnie zmienna podana do podprogramu jako zmienna zwrotna (curr_arg_value) jest testowana pod kątem niezdefiniowania, co miałoby miejsce, gdyby obecnie oceniany argument wiersza poleceń był nieobecny. Początkowo było to porównanie wartości zwracanej zmiennej owiniętej w nawiasy kwadratowe z pustymi nawiasami kwadratowymi (co jest jedynym sposobem, jaki znam z testowania programu lub podprogram argumentów, które mogą zawierać cudzysłowy i był pominięty resztki z fazy prób i błędów), ale od tego czasu został ustalony, jak to jest teraz.

 2
Author: fen-fire,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-16 11:24:37

Ostatnia odpowiedź była dwa lata temu, ale potrzebowałem wersji dla więcej niż dziewięciu argumentów linii poleceń. Może inny też tak robi...

@echo off
setlocal

set argc_=1
set arg0_=%0
set argv_=

:_LOOP
set arg_=%1
if defined arg_ (
  set arg%argc_%_=%1
  set argv_=%argv_% %1
  set /a argc_+=1
  shift
  goto _LOOP
)
::dont count arg0
set /a argc_-=1
echo %argc_% arg(s)

for /L %%i in (0,1,%argc_%) do (
  call :_SHOW_ARG arg%%i_ %%arg%%i_%%
)

echo converted to local args
call :_LIST_ARGS %argv_%
exit /b


:_LIST_ARGS
setlocal
set argc_=0
echo arg0=%0

:_LOOP_LIST_ARGS
set arg_=%1
if not defined arg_ exit /b
set /a argc_+=1
call :_SHOW_ARG arg%argc_% %1
shift
goto _LOOP_LIST_ARGS


:_SHOW_ARG
echo %1=%2
exit /b

Rozwiązaniem jest pierwsze 19 linii i konwertuje wszystkie argumenty na zmienne w stylu C. Wszystkie inne rzeczy po prostu sonduje wynik i pokazuje konwersję do lokalnych args. Możesz odwoływać się do argumentów za pomocą indeksu w dowolnej funkcji.

 1
Author: Kasimir,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-10 10:20:35