Пакетные разделители по параметрам - PullRequest
0 голосов
/ 16 ноября 2018

Я нашел следующую команду, чтобы получить все, кроме первых двух параметров:
for /f "tokens=2,*" %%a in ("%*") do set AFTER_SECOND=%%b
Моя проблема в том, что я должен использовать "^" и "," в моей команде, но пакет видит их как разделители и не пропускает их.
Я пытался передать это: "2,5^^3", но чем это не пройдет ","
Спасибо за помощь!

1 Ответ

0 голосов
/ 17 ноября 2018

Откройте окно командной строки и запустите cmd /?, чтобы получить справку для командного процессора Windows.Последняя страница справки объясняет в последнем абзаце, когда особенно имя файла (или любая другая строка аргумента) должно быть заключено в двойные кавычки, т.е. строка аргумента содержит пробел или один из этих символов &()[]{}^=;!'+,`~<|>.Обратите внимание, что <|> недопустимы в именах файлов / папок, но возможны в общих строках аргументов.

Следующий запуск в окне командной строки call /?.Справка по выводу объясняет, как можно ссылаться на аргументы пакетного файла, включая ссылку на все переданные аргументы %*, которая ссылается на все строки аргумента точно так, как они переданы в пакетный файл, за исключением аргумента 0, который точно является именем пакетного файлакак указано пользователем при запуске пакетного файла из окна командной строки.

Теперь давайте рассмотрим очень простой пакетный файл с именем Test.bat:

@echo off
echo %0 %*
for /F "tokens=3*" %%I in ("%*") do echo FOR: %%I %%J
pause

Test.bat выполняется из окна командной строки с помощью:

Test 1 2 3 4 5 6

Вторая командная строка выводит в точности строку, как написано выше.

Но что делает FOR вв этом случае?

Выполнение for /? в окне командной строки выводит справку команды FOR и объясняет параметр /F, а также значение tokens=3*.

FOR ожидает здесь строку, заключенную в двойные кавычки, например "..." с пробелами / табуляциями , а не , содержащие двойные кавычки.Эта строка должна быть разбита на подстроки с использованием пробелов / табуляций, если они не начинаются с символа конца строки (eol) по умолчанию ;, при этом третья подстрока с пробелом / табуляцией должна быть назначена указанной переменной цикла Iи остаток строки после пробелов / табуляции после третьей подстроки должен быть назначен следующей переменной в соответствии с ASCII таблицей , которая в данном случае будет J.

Таким образом, результат будет таким, как ожидалось:

Test 1 2 3 4 5 6
FOR: 3 4 5 6

В командной строке FOR выводятся данные о запуске:

Test ;1 2 3 4 5 6

Причиной по умолчанию является eol=; и точка с запятой в начале строки обрабатывается FOR .Только вторая командная строка выводит используемую командную строку для запуска командного файла.Таким образом, вывод просто: Test ;1 2 3 4 5 6

Далее мы запускаем Test.bat с:

Test 1 2 3

Вывод:

Test 1 2 3
FOR: 3 

Есть пробел навывод строки с помощью FOR .

Но что происходит при запуске командного файла с использованием следующей командной строки?

Test.bat "First argument" "1, 2, 3 in second argument" "^ caret in third argument" "and so on"

Вторая командная строка выводит эту строку.Но FOR должен обработать:

""First argument" "1, 2, 3 in second argument" "^ caret in third argument" "and so on""

FOR не в состоянии полностью интерпретировать эту строку, как вы ожидали, содержащую несколько двойных кавычек, то есть в реальных многократных аргументных строках вустановить для обработки.

Итак, как получить все аргументы, игнорируя первые две строки аргументов, в переменную окружения, разделенную пробелами, для последующей обработки этой строки, объединенной из нескольких строк аргументов пакетного файла?

OneРешение заключается в использовании команды SHIFT в цикле вместе с командой SET .

@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "AllArguments="

:ArgLoop
set "Argument=%~3"
if defined Argument (
    set "AllArguments=%AllArguments% %Argument%"
    shift /3
    goto ArgLoop
)
rem Is there no more argument or is the argument string just empty?
set "Argument=%3"
if defined Argument shift /3 & goto ArgLoop

rem All argument strings processed, remove first space from the concatenated string.
if defined AllArguments set "AllArguments=%AllArguments:~1%"

cls
echo The batch file was called with:
echo/
echo %0 %*
echo/
echo All arguments starting from third argument are:
echo/
echo "%AllArguments%"
echo/
endlocal
pause

Этот пакетный файл с именем Test.bat, например, выполняется с помощью:

Test.bat "First argument" SecondArgument "^ caret in third argument" "" "Fifth argument!" "1,2,3 | 233 < 234 > 235" "& more arguments" "without or" with,double;quotes=whereby "by mistake last argument has a double" quote at end"

Это действительно ужасный список аргументов для обработки его с помощью пакетного файла.

  • В третьей строке аргумента есть escape-символ ^, интерпретируемый как литеральный символ внутриСтрока аргумента с двойными кавычками.
  • Четвертая строка аргумента является пустой строкой аргумента.
  • В пятом a есть !Строка rgument, которая интерпретируется как начало / конец ссылки на переменную среды с задержкой, если отложенное расширение будет включено в пакетном файле даже при нахождении внутри строки аргумента с двойными кавычками.
  • Следующая строка аргумента содержит разделитель аргументов , иоператоры перенаправления |, < и > интерпретируются как литеральные символы из-за нахождения в строке аргумента в двойных кавычках.
  • Оператор & также включен, который имеет несколько значений, например, при перенаправлении с 2>&1 или для несколько команд в одной командной строке , но интерпретируется здесь как буквенный символ, поскольку он также находится внутри двойного строка в кавычках.
  • Есть ,, ; и = не внутри строки аргумента с двойными кавычками и поэтому интерпретируются как разделители аргументов cmd.exe.
  • И последний, но не менее важный аргумент заканчивается на ", но не начинается на ".

Вывод этой командной строки с указанным выше командным файлом с 80 столбцами в строке:

The batch file was called with:

Test.bat "First argument" SecondArgument "^ caret in third argument" "" "Fifth a
rgument!" "1,2,3 | 233 < 234 > 235" "& more arguments" "without or" with,double;
quotes=whereby "by mistake last argument has a double" quote at end"

All arguments starting from third argument are:

"^ caret in third argument Fifth argument! 1,2,3 | 233 < 234 > 235 & more argume
nts without or with double quotes whereby by mistake last argument has a double
quote at end""

Хорошо выглядит, не правда ли.

Кстати: было бы неплохо выводить значение %AllArguments% без использования двойных кавычек в этом случае, потому что все эти символы имеют специальные значения для cmd.exe вне строки аргумента с двойными кавычками. Но можно заменить echo "%AllArguments%" на setlocal EnableDelayedExpansion & echo !AllArguments!& endlocal, чтобы вывести строковое значение переменной среды AllArguments без двойных кавычек с использованием отложенного раскрытия. См. Также Как синтаксический анализ сценариев интерпретатора команд Windows (CMD.EXE)?

Примечание 1: Команда SHIFT не изменяет строку всех переданных аргументов , на которую ссылается %*, как показывает этот пакетный файл. Он изменяет только нумерованные ссылки на аргументы, используемые этим пакетным файлом для обработки всегда третьего аргумента в цикле, пока на самом деле не останется больше аргументов.

Примечание 2: Максимальный размер переменной среды составляет 8192 байта, включая байты для имени переменной, один знак равенства (разделитель между именем и значением) и завершающий нулевой байт строку. Другими словами, максимальная длина, назначаемая переменной среды, равна: 8192 - 2 - длина имени переменной

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

  • call /?
  • cls /?
  • echo /?
  • endlocal /?
  • goto /?
  • if /?
  • rem /?
  • set /?
  • setlocal /?
  • shift /?

PS: Я совершенно уверен, что этот код все еще не обрабатывает все комбинации аргументов правильно, но он должен работать почти во всех случаях использования.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...