Как заставить SHIFT работать с% * в пакетных файлах - PullRequest
34 голосов
/ 20 февраля 2012

В моем командном файле в Windows XP я хочу использовать %* для расширения всех параметров, кроме первого. Тестовый файл ( foo.bat ):

@echo off
echo %*
shift
echo %*

Вызов:

C:\> foo a b c d e f

Фактический результат:

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

Желаемый Результат:

a b c d e f
b c d e f

Как мне достичь желаемого результата?Спасибо !!

Ответы [ 6 ]

20 голосов
/ 20 февраля 2012

Не было бы замечательно, если бы CMD.EXE работал таким образом! К сожалению, нет хорошего синтаксиса, который будет делать то, что вы хотите. Лучшее, что вы можете сделать, - это самостоятельно проанализировать командную строку и создать новый список аргументов.

Нечто подобное может работать.

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

Но вышеописанное имеет проблемы, если аргумент содержит специальные символы, такие как ^, &, >, <, |, которые были экранированы вместо кавычек.

Обработка аргументов является одним из многих слабых сторон пакетного программирования Windows. Практически для каждого решения существует исключение, которое вызывает проблемы.

3 голосов
/ 26 мая 2015

Это просто:

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

  echo/%_args%
endlocal

То же самое с комментариями:

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

Пример:

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

Примечания:

  • Не работает, если какой-либо аргумент содержит! или & char
  • Любые лишние пробелы между аргументами НЕ будут удалены
3 голосов
/ 20 февраля 2012

Не думайте, что есть простой способ сделать это.Вместо этого вы можете попробовать поиграть со следующим обходным решением:

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

Пример:

test.bat 1 2 3=4

Вывод:

2 3=4
1 голос
/ 10 марта 2017

Я должен был сделать это недавно и придумал следующее:

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

Он использует цикл для пропуска N первых аргументов.Может использоваться для выполнения некоторой команды для каждого аргумента или для создания нового списка аргументов:

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

Обратите внимание, что приведенный выше код добавит начальный пробел к новым аргументам.Его можно удалить следующим образом:

0 голосов
/ 25 апреля 2018

Возобновите все и исправьте все проблемы:

set Args=%1
:Parse
shift
set First=%1
if not defined First goto :EndParse
  set Args=%Args% %First%
  goto :Parse
:EndParse

Не поддерживать пробелы между аргументами: 1 2 3 4 будет 1 2 3 4

0 голосов
/ 11 мая 2016

Еще один простой способ сделать это:

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

echo/%_args%

Замечания:

  • Не работает, если первый аргумент (% 1) заключен в кавычки'или "двойные кавычки"
  • Не работает, если какой-либо аргумент содержит & char
  • Любые лишние пробелы между аргументами НЕ будут удалены
...