Как вы используете более 9 аргументов при вызове метки в пакете CMD - script?
Я хотел бы знать, как вызывать более 9 аргументов в пакете script при вызове метки. Например, следующее показывает, что у меня есть 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 заканчивается как один0 один1 один2. Я пробовал использовать фигурные скобки, скобки, цитаты, одинарные кавычки вокруг чисел без везения.
Ответы
Ответ 1
Для этого существует shift
команда.
Вы можете либо использовать цикл, хранить переменные перед переносом, либо делать это быстро:
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
shift
shift
shift
echo %7
echo %8
echo %9
Вы можете заменить команды shift на цикл, если у вас много аргументов. Следующий цикл for выполняет shift
девять раз, так что %1
будет десятым аргументом.
@for /L %%i in (0,1,8) do shift
Ответ 2
Это еще один способ использования команды 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
Ответ 3
У вас не может быть более 10 (от 0 до 9) доступных аргументов (% 0 - сам пакетный файл) в пакетном файле. Однако использование команды shift
позволит вам "сдвигать влево" ваши аргументы и получать доступ к этим аргументам за пределами 9-го. Если вы делаете это три раза, вы должны получить% 7,% 8 и% 9, содержащие "десять", "одиннадцать" и "двенадцать".
Ответ 4
Предполагая, что мы используем недавнюю версию CMD здесь, я очень шокирован тем, что никто не опубликовал следующее, что позволяет легко обрабатывать произвольное количество аргументов без использования неуклюжей shift
команда:
rem test.bat
call :subr %*
exit /b
:subr
for %%A in (%*) do (
echo %%A
)
exit /b
Вы также можете сделать эту же технику прямо в "основном".
Таким образом, вы не едите свои аргументы при их обработке, и существует необходимость в shift
, что означает, что вы можете последовательно перебирать список аргументов более одного раза, если у вас есть сложные параметры вызова, и это происходит чтобы сделать вашу логику script более простой.
Очевидно, что если цикл повторяется не один раз, он увеличивает вычислительную сложность в обмен на разборчивость, но ни Bash, ни CMD не были действительно построены для большой скорости (насколько я когда-либо слышал), поэтому в пытаясь оптимизировать, выполняя настройку all-in-one-go, предполагая, что 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 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*
.
Ответ 5
Просто бросать шляпу в кольцо, если это кому-то помогает
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 args, тогда вы можете использовать %a%
через %z%
вместо %1
для несуществующего %26
.
Это довольно уродливо, изначально у меня была одна одна линия à la
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"