2012-02-20 15 views
30

W moim pliku wsadowym w systemie Windows XP chcę użyć %*, aby rozwinąć wszystkie parametry oprócz pierwszego. Plik
test (foo.bat):Jak sprawić, aby SHIFT działał z% * w plikach wsadowych

@echo off 
echo %* 
shift 
echo %* 

Call:

C:\> foo a b c d e f 

Rzeczywista wynik:

a b c d e f 
a b c d e f 

Pożądany wynik:

a b c d e f 
b c d e f 

Jak mogę osiągnąć pożądany rezultat? Dzięki!!

Odpowiedz

17

Czy nie byłoby wspaniale, gdyby CMD.EXE działało w ten sposób! Niestety nie ma dobrej składni, która zrobi to, co chcesz. Najlepsze, co możesz zrobić, to samemu przetworzyć linię poleceń i zbudować nową listę argumentów.

Coś takiego może działać.

@echo off 
setlocal 
echo %* 
shift 
set "args=" 
:parse 
if "%~1" neq "" (
    set args=%args% %1 
    shift 
    goto :parse 
) 
if defined args set args=%args:~1% 
echo(%args% 

Ale powyżej ma problemy, jeśli argument zawiera znaki specjalne jak ^, &, >, <, | które zostały uciekł zamiast cytowane.

Obsługa argumentów jest jednym z wielu słabych aspektów programowania wsadowego systemu Windows. Dla prawie każdego rozwiązania istnieje wyjątek, który powoduje problemy.

3

Nie myśl, że jest prosty sposób na zrobienie tego. Można spróbować gry z następującym obejście Zamiast:

@ECHO OFF 
>tmp ECHO(%* 
SET /P t=<tmp 
SETLOCAL EnableDelayedExpansion 
IF DEFINED t SET "t=!t:%1 =!" 
ECHO(!t! 

Przykład:

test.bat 1 2 3=4 

wyjściowa:

2 3=4 
+0

nie widzę korzyści z pliku tymczasowego - zbiór T = '*'% będzie działać tak samo dobrze. Ta odpowiedź nie powiedzie się, jeśli% 1 zawiera '=' lub zaczyna się od '*' lub '~'. Również będą miały problemy, jeśli argumenty są rozdzielane za pomocą ',' lub ';' zamiast spacji. Lepiej usunąć tylko% 1 i pozostawić ograniczniki w miejscu. – dbenham

+0

Problem z zabójcą - ta odpowiedź da błędną odpowiedź, jeśli argumenty są "A A B". Można poprawić za pomocą 'set t =! T: *% 1 =!' – dbenham

+0

Użycie 'set" t =! T: *% 1 =! 'Modyfikacja, ta odpowiedź nadal się nie powiedzie, jeśli% 1 zawiera' = ', ale zaczyna z '*' lub '~' jest ok. – dbenham

2

That's proste:

setlocal ENABLEDELAYEDEXPANSION 
    set "_args=%*" 
    set "_args=!_args:*%1 =!" 

    echo/%_args% 
endlocal 

samo z c WAGI:

:: Enable use of ! operator for variables (! works as % after % has been processed) 
setlocal ENABLEDELAYEDEXPANSION 
    set "_args=%*" 
    :: Remove %1 from %* 
    set "_args=!_args:*%1 =!" 
    :: The %_args% must be used here, before 'endlocal', as it is a local variable 
    echo/%_args% 
endlocal 

Przykład:

lets say %* is "1 2 3 4": 

setlocal ENABLEDELAYEDEXPANSION 
    set "_args=%*"    --> _args=1 2 3 4 
    set "_args=!_args:*%1=!" --> _args=2 3 4 

    echo/%_args% 
endlocal 

Uwagi:

  • nie działa, jeśli każdy argument zawiera!lub & char
  • Wszelkie dodatkowe spacje między argumentami NIE zostanie usunięty
+0

Musisz usunąć argument% 1, a nie% 0 (który jest nazwą skryptu) –

+0

Rzeczywiście masz rację. Edytowałem% 0 do% 1 teraz. Dzięki. – cyberponk

+2

Jak napisano, jest to niebezpiecznie błędne, ponieważ wartość pierwszego argumentu może zostać powtórzona w kolejnym arg, a twój kod usunie oba. Można to naprawić, używając '*', aby usunąć wszystko przez pierwszą instancję: 'set _args =! _ Args: *% 1 =!'. Inne problemy, których nie można naprawić, nie powiedzie się, jeśli '% 1' zawiera'! 'Lub' = '. – dbenham

0

Innym sposobem na to jest:

set "_args=%*" 
set "_args=%_args:* =%" 

echo/%_args% 

Uwagi:

  • nie działa jeśli pierwszy argument (% 1) to "kwotowany" lub "podwójny cudzysłów"
  • nie działa, jeśli każdy argument zawiera & char
  • żadnych dodatkowych spacji pomiędzy argumentami nie zostaną usunięte
1

musiałem to zrobić niedawno i podszedł z tym:

setlocal EnableDelayedExpansion 

rem Number of arguments to skip 
set skip=1 

for %%a in (%*) do (
    if not !position! lss !skip! (
    echo Argument: '%%a' 
) else (
    set /a "position=!position!+1" 
) 
) 

endlocal 

IT używa pętli, aby pominąć N pierwszych argumentów. Może być stosowany do wykonywania niektórych poleceń za argumentu lub zbudować nową listę argumentów:

setlocal EnableDelayedExpansion 

rem Number of arguments to skip 
set skip=1 

for %%a in (%*) do (
    if not !position! lss !skip! (
    set args=!args! %%a 
) else (
    set /a "position=!position!+1" 
) 
) 

echo %args% 

endlocal 

Proszę zwrócić uwagę, że powyższy kod doda przestrzeń prowadzącą do nowych argumentów. Można go usunąć tak:

Powiązane problemy