Как вы используете более 9 аргументов при вызове метки в пакетном скрипте CMD? - PullRequest
23 голосов
/ 30 ноября 2011

Я хотел бы знать, как вызывать более 9 аргументов в пакетном скрипте при вызове метки.Например, следующее показывает, что у меня есть 12 назначенных аргументов вместе с попыткой отобразить их все.

CALL:LABEL "one" "two" "three" "four" "five" "six" "seven" "eight" "nine" "ten" "eleven" "twelve"
PAUSE
GOTO:EOF


:LABEL
echo %1
echo %2
echo %3
echo %4
echo %5
echo %6
echo %7
echo %8
echo %9
echo %10
echo %11
echo %12

Выходные данные для% 10% 11 и% 12 заканчиваются на one0 one1 one2.Я безуспешно пытался использовать фигурные скобки, скобки, цитаты, одинарные кавычки вокруг чисел.

Ответы [ 5 ]

26 голосов
/ 30 ноября 2011

Используйте команду shift , если хотите работать с более 9 параметрами.
(на самом деле более 10 параметров, если считать параметр %0)

Вы можете [...] использовать команду shift для создания пакетного файла, который может принимать более 10 пакетных параметров.Если в командной строке указано более 10 параметров, те, которые появляются после десятого (% 9), будут смещаться по одному в% 9.

Вы можете использовать цикл, сохранитьпеременные перед сдвигом, или сделайте это быстро, как это:

@echo off
CALL:LABEL "one" "two" "three" "four" "five" "six" "seven" "eight" "nine" "ten" "eleven" "twelve"
PAUSE
GOTO:EOF

:LABEL
:: print arguments 1-9
echo %1
echo %2
echo %3
echo %4
echo %5
echo %6
echo %7
echo %8
echo %9

:: print arguments 10-11
shift
shift 
echo %8
echo %9

:: print argument 13
shift
echo %9

Вы можете заменить команды сдвига циклом, если у вас много аргументов.Следующий цикл for выполняется shift девять раз, так что %1 будет десятым аргументом.

@for /L %%i in (0,1,8) do shift
6 голосов
/ 27 апреля 2015

Предполагая, что мы используем недавно выпущенную версию CMD, я очень шокирован, обнаружив, что никто не опубликовал следующее, что позволяет легко обрабатывать произвольное количество аргументов, даже не используя clunky shift команда:

rem test.bat
call :subr %*
exit /b

:subr
for %%A in (%*) do (
    echo %%A
)
exit /b

Вы также можете сделать эту же технику прямо в "main".

Таким образом, вы не съедаете свои аргументы при их обработке, и вам не нужно shift, то есть вы можете последовательно просматривать список аргументов более одного раза, если у вас есть сложные параметры вызова и случается, чтобы сделать логику вашего скрипта проще.

Очевидно, что если do повторяется более одного раза, это увеличивает вычислительную сложность в обмен на удобочитаемость, но ни Bash, ни CMD действительно не были созданы для большой скорости (насколько я когда-либо слышал), поэтому нет смысла пытаться оптимизировать, выполняя настройку «все в одном», предполагая, что n меньше 100 или около того.

Пример вывода:

C:\tmp>test.bat one two three four five six seven eight nine ten eleven
one
two
three
four
five
six
seven
eight
nine
ten
eleven

edit - Если кто-то обрабатывает аргументы против другого списка, и часть работы вложена, важно использовать посредника CALL, чтобы разрешить передачу текущего обрабатываемого аргумента во внутренний цикл; простое выполнение set intermediary=%%OUTER, по-видимому, просто устанавливает intermediary на пустую строку, так что это проще всего сделать следующим образом:

setlocal enabledelayedexpansion
rem ^ in my experience, it's always a good idea to set this if for-loops are involved
for /f %%L in (file.txt) do (
    call :inner %%L
)
exit /b

:inner
for %%A in (%*) do (
    if %%A EQU %~1 call dosomething.bat %~1        
)
exit /b

edit 2 - Кроме того, если по какой-либо причине вы хотите добавить сюда подход shift в микс - возможно, пытаясь передать все аргументы, кроме первого, в подпрограмму с помощью shift, а затем с помощью call :subroutine %* - обратите внимание, что не будет работать , потому что %* фактически выдает все исходные аргументы по порядку, не обращая внимания на любые изменения, которые вы сделали.
Обидно, потому что нет собственного синтаксиса (который я знаю), который мог бы сгруппировать все аргументы после определенного, как можно было бы ожидать, скажем, %3*.

6 голосов
/ 07 ноября 2013

Это еще один способ использования команды shift.

Обратите внимание, что в этом случае вы можете использовать переменное количество параметров.

@ECHO OFF
CALL:LABEL "one" "two" "three" "four" "five" "six" "seven" "eight" "nine" "ten" "eleven" "twelve"
PAUSE
GOTO:EOF

:LABEL
echo %1
shift
if not [%1]==[] GOTO LABEL
4 голосов
/ 30 ноября 2011

Вы не можете иметь более 10 (от 0 до 9) доступных аргументов (% 0 - это сам пакетный файл) в пакетном файле.Однако использование команды shift позволит вам «сдвинуть» ваши аргументы влево и получить доступ к этим аргументам за пределами 9-го.Если вы сделаете это три раза, вы должны получить% 7,% 8 и% 9, содержащие «десять», «одиннадцать» и «двенадцать».

2 голосов
/ 15 июля 2016

Просто бросив мою шляпу в кольцо, если это кому-нибудь поможет

Set a=%1 & Set b=%2 & Set c=%3 & Set d=%4 & Set e=%5 & Set f=%6 & Set g=%7 & Set h=%8 & Set i=%9
Shift & Shift & Shift & Shift & Shift & Shift & Shift & Shift & Shift
Set j=%1 & Set k=%2 & Set l=%3 & Set m=%4 & Set n=%5 & Set o=%6 & Set p=%7 & Set q=%8 & Set r=%9
Shift & Shift & Shift & Shift & Shift & Shift & Shift & Shift & Shift
Set s=%1 & Set t=%2 & Set u=%3 & Set v=%4 & Set w=%5 & Set x=%6 & Set y=%7 & Set z=%8

Я просто поместил это в верхнюю часть .bat или подпрограмму, которая будет использовать> 9 аргументов, тогда вы можете использовать %a% через %z% вместо %1 к несуществующему %26.

Это довольно уродливо, изначально у меня было все это одной строкой а-ля

Set a=%1 & Shift & Set b=%1 & Shift &...

Таким образомон только на одной строке и довольно быстро скрывается за границей редактора, но, очевидно, Shift не вступит в силу до следующей истинной строки;все переменные были установлены на первый параметр.

Если вам интересно, зачем делать это вместо циклов, если кто-то не покажет мне, что вы можете создать своего рода карту или массив, мне нужно было использовать переменные воднострочная команда, а не echo (или что-то еще) с ними по одному:

::example; concatenate a bunch of files
Set output=%1
Shift
<insert above behemoth>
type %a% %b% %c% %d% %e% %f% 2>NUL > %output%

Черт, это было намного проще в bash

cat ${@:2} > "$1"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...