2012-02-20 12 views
30

En mi archivo por lotes en Windows XP, deseo usar %* para expandirlo a todos los parámetros, excepto el primero.
archivo prueba (foo.bat):Cómo hacer que SHIFT funcione con% * en archivos de proceso por lotes

@echo off 
echo %* 
shift 
echo %* 

Llamar:

C:\> foo a b c d e f 

real resultado:

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

deseado resultado:

a b c d e f 
b c d e f 

¿Cómo puedo lograr el resultado deseado? ¡¡Gracias!!

Respuesta

17

¡No sería maravilloso si CMD.EXE funcionara de esa manera! Desafortunadamente no hay una buena sintaxis que haga lo que quieras. Lo mejor que puede hacer es analizar la línea de comandos usted mismo y crear una nueva lista de argumentos.

Algo como esto puede funcionar.

@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% 

Pero lo anterior tiene problemas si un argumento contiene caracteres especiales como ^, &, >, <, | que se escapó en lugar de cita.

El manejo de argumentos es uno de los muchos aspectos débiles de la programación por lotes de Windows. Para casi todas las soluciones, existe una excepción que causa problemas.

3

No creo que haya una manera simple de hacerlo. Usted podría intentar jugar con la siguiente solución en su lugar:

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

Ejemplo:

test.bat 1 2 3=4 

Salida:

2 3=4 
+0

no veo el beneficio del archivo temporal - 'set t =% *' funcionaría igual de bien. Esta respuesta fallará si% 1 contiene '=' o comienza con '*' o '~'. También tendrá problemas si los argumentos están delimitados con ',' o ';' en lugar de espacios. Mejor eliminar solo% 1 y dejar los delimitadores en su lugar. – dbenham

+0

Problema de asesino: esta respuesta dará una respuesta incorrecta si args son 'A A B'. Podría mejorarse con 'set t =! T: *% 1 =!' – dbenham

+0

Usando 'set" t =! T: *% 1 =! 'Modificación, esta respuesta todavía fallará si% 1 contiene' = ', pero iniciando con '*' o '~' está bien. – dbenham

2

Eso es fácil:

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

    echo/%_args% 
endlocal 

La misma cosa con c OBSERVACIONES:

:: 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 

Ejemplo:

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 

Observaciones:

  • No funciona si cualquier argumento contiene el!o & carbón
  • no se eliminará espacios adicionales en el medio argumentos
+0

Debe eliminar el argumento% 1, no el% 0 (que es el nombre del script) –

+0

De hecho, tiene razón. He editado% 0 a% 1 ahora. Gracias. – cyberponk

+2

Tal como está escrito, esto está peligrosamente mal, porque el valor para la primera arg podría repetirse en una arg posterior, y su código eliminará ambos. Eso podría solucionarse usando '*' para eliminar todo a través de la primera instancia: 'set _args =! _ Args: *% 1 =!'. Otros problemas que no pueden corregirse es que fallarán si '% 1' contiene'! 'O' = '. – dbenham

0

Otra manera fácil de hacer esto es:

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

echo/%_args% 

Observaciones:

  • no funciona si el primer argumento (% 1) es 'entre comillas' o '' doble entre comillas ''
  • no funciona si cualquier argumento contiene los & carbón
  • Cualquier espacio extra entre los argumentos no se eliminarán
1

que tenía que hacer esto recientemente y se acercó con esto:

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 

Se utiliza el bucle para omitir los primeros argumentos de N. Puede ser utilizado para ejecutar alguna orden por discusión o construir nueva lista de argumentos:

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 

Tenga en cuenta que el código anterior se sumará el espacio que conduce a los nuevos argumentos. Se puede extraer de esta manera:

Cuestiones relacionadas