Я хотел бы знать, как вызвать более 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. Я пробовал использовать фигурные скобки, скобки, кавычки, одинарные кавычки вокруг чисел безрезультатно.
Используйте команду 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
Это еще один способ использовать команду 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
Предполагая, что мы используем недавно выпущенную версию CMD, я очень шокирован, обнаружив, что никто не опубликовал следующее, что позволяет легко обрабатывать произвольное количество аргументов, даже не используя clunky shift
. команда:
rem test.bat
call :subr %*
exit /b
:subr
for %%A in (%*) do (
echo %%A
)
exit /b
Вы можете также сделать эту же технику прямо в "main".
Таким образом, вы не съедаете свои аргументы, когда обрабатываете их, и нет необходимости в shift
, то есть вы можете последовательно просматривать список аргументов более одного раза, если у вас сложный вызов опций, и это делает логику вашего скрипта проще.
Очевидно, что если делать цикл более одного раза, это увеличивает вычислительную сложность в обмен на удобочитаемость, но ни 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
в микс - возможно, попытавшись передать все аргументы, кроме 1-го, подпрограмме, используя shift
, а затем - call :subroutine %*
- обратите внимание, что он не будет работа , потому что %*
на самом деле дает вам все исходные аргументы в порядке, не обращая внимания на любые изменения, которые вы сделали.
Это позор, потому что нет собственного синтаксиса (который я знаю), который мог бы сгруппировать все аргументы после определенного, как можно было бы ожидать, скажем, %3*
.
Просто бросая мою шляпу в кольцо, если это кому-нибудь поможет.
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"