Мы проводили эксперименты по изучению грамматики пакетных скриптов. Мы также исследовали различия между пакетным режимом и режимом командной строки.
Пакетный анализатор строк:
Вот краткий обзор фаз в парсере строк командного файла:
Фаза 0) Читать строку:
Фаза 1) Процентное расширение:
Этап 2) Обработка специальных символов, токенизация и построение кэшированного командного блока: это сложный процесс, на который влияют такие вещи, как кавычки, специальные символы, разделители токенов и переходы курсора.
Фаза 3) Эхо проанализированных команд (команд) Только в том случае, если командный блок не начинается с @
, а ECHO был включен в начале предыдущего шага.
Фаза 4) %X
Расширение переменной FOR : только если активна команда FOR и выполняются команды после DO.
Фаза 5) Отложенное расширение: только если включено отложенное расширение
Фаза 5.3) Обработка трубы: только если команды находятся по обе стороны трубы.
Фаза 5.5) Выполнить перенаправление:
Фаза 6) Обработка CALL / удвоение символа каретки: только если токен команды CALL
Фаза 7) Выполнить: команда выполняется.
Вот подробности для каждого этапа:
Обратите внимание, что этапы, описанные ниже, являются лишь моделью того, как работает пакетный анализатор. Фактическое внутреннее устройство cmd.exe может не отражать эти фазы. Но эта модель эффективна при прогнозировании поведения пакетных сценариев.
Фаза 0) Прочитать строку: сначала прочитать строку ввода <LF>
.
- При чтении строки, которая будет проанализирована как команда,
<Ctrl-Z>
(0x1A) читается как <LF>
(LineFeed 0x0A)
- Когда GOTO или CALL считывают строки при сканировании метки:,,
<Ctrl-Z>
обрабатываются как сами по себе - они не преобразуются в<LF>
Фаза 1) Процентное расширение:
- Двойной
%%
заменяется одиночным%
- Расширение аргументов (
%*
, %1
, %2
и т.д.)
- Расширение
%var%
, если var не существует, заменить его ничем
- Строка сначала обрезается
<LF>
вне %var%
раскрытия
- Для полного объяснения прочтите первую половину этого из dbenham Та же ветка: Процентная фаза
Этап 2) Обработка специальных символов, токенизация и построение кэшированного командного блока: это сложный процесс, на который влияют такие вещи, как кавычки, специальные символы, разделители токенов и переходы курсора. Ниже приводится приблизительное описание этого процесса.
Есть концепции, которые важны на этом этапе.
- Токен - это просто строка символов, которая рассматривается как единое целое.
- Токены разделяются разделителями токенов. Стандартные разделители токенов - это
<space>
<tab>
;
,
=
<0x0B>
<0x0C>
и <0xFF>
последовательные разделители токенов обрабатываются как один - между разделителями токенов нет пустых токенов.
- Внутри строки в кавычках нет разделителей токенов. Вся строка в кавычках всегда рассматривается как часть одного токена. Один токен может состоять из комбинации строк в кавычках и символов без кавычек.
Следующие символы могут иметь особое значение на этом этапе, в зависимости от контекста: <CR>
^
(
@
&
|
<
>
<LF>
<space>
<tab>
;
,
=
<0x0B>
<0x0C>
<0xFF>
Посмотрите на каждого символа слева направо:
- Если
<CR>
затем удалить его, как будто его никогда не было (за исключением странного поведения перенаправления )
- Если используется каретка (
^
), следующий символ экранируется, а экранирующая вставка удаляется. Экранированные символы теряют все специальные значения (кроме <LF>
).
- Если кавычка (
"
), переключить флаг кавычки. Если флажок котировки активен, то особенными являются только "
и <LF>
. Все остальные символы теряют свое особое значение до тех пор, пока следующая цитата не отключит флаг кавычки. Невозможно избежать заключительной цитаты. Все цитируемые символы всегда находятся в одном токене.
<LF>
всегда выключает флаг цитаты. Другое поведение зависит от контекста, но цитаты никогда не меняют поведения <LF>
.
- Сбежал
<LF>
<LF>
раздевается
- Следующий символ экранирован. Если в конце строки буфера, то следующая строка читается и обрабатывается фазами 1 и 1.5 и добавляется к текущей перед экранированием следующего символа. Если следующий символ - это
<LF>
, он рассматривается как литерал, что означает, что этот процесс не рекурсивный.
- Без экранирования
<LF>
без скобок
<LF>
удаляется, и анализ текущей строки прекращается.
- Любые оставшиеся символы в строковом буфере просто игнорируются.
- Неэкранирование
<LF>
в блоке FOR IN в скобках
<LF>
превращается в <space>
- Если в конце строки буфера, то считывается следующая строка и добавляется к текущей.
- Без экранирования
<LF>
в командном блоке в скобках
<LF>
преобразуется в <LF><space>
, и <space>
рассматривается как часть следующей строки командного блока.
- Если в конце строки буфера, то следующая строка считывается и добавляется к пробелу.
- Если один из специальных символов
&
|
<
или >
, разделите строку в этой точке, чтобы обрабатывать каналы, конкатенацию команд и перенаправление.
- В случае pipe (
|
) каждая сторона представляет собой отдельную команду (или командный блок), которая получает особую обработку на этапе 5.3.
- В случае
&
, &&
или ||
команда конкатенации, каждая сторона конкатенации рассматриваются в качестве отдельной команды.
- В случае
<
, <<
, >
или >>
перенаправления, положение перенаправления анализируется, временно удален, а затем добавляется к концу текущей команды. Предложение перенаправления состоит из необязательной цифры дескриптора файла, оператора перенаправления и маркера назначения перенаправления.
- Если токен, предшествующий оператору перенаправления, представляет собой одну неэкранированную цифру, то эта цифра указывает дескриптор файла, который необходимо перенаправить. Если маркер дескриптора не найден, то перенаправление вывода по умолчанию равно 1 (стандартный вывод), а перенаправление ввода по умолчанию - 0 (стандартный ввод).
- Если самый первый токен для этой команды (до перемещения перенаправления в конец) начинается с
@
, то @
имеет особое значение. ( @
не является особенным ни в каком другом контексте)
- Спец
@
снимается.
- Если ECHO включен, то эта команда вместе со всеми последующими объединенными командами в этой строке исключается из эха фазы 3. Если
@
стоит перед открытием (
, то весь заключенный в скобки блок исключается из эхо-сигнала фазы 3.
- Скобки процесса (предусматривают составные операторы в нескольких строках):
- Если парсер не ищет токен команды, то в
(
этом нет ничего особенного.
- Если синтаксический анализатор ищет токен команды и находит
(
, то запускает новый составной оператор и увеличивает счетчик скобок
- Если счетчик скобок> 0,
)
завершает составной оператор и уменьшает счетчик скобок.
- Если достигнут конец строки и счетчик скобок> 0, то следующая строка будет добавлена к составному оператору (снова начинается с фазы 0)
- Если счетчик скобок равен 0 и синтаксический анализатор ищет команду, то
)
функции аналогичны REM
оператору, если за ним сразу следует разделитель токенов, специальный символ, новая строка или конец файла.
- Все специальные символы теряют свое значение, кроме
^
(возможна конкатенация строк)
- По достижении конца логической строки вся «команда» отбрасывается.
- Каждая команда разбивается на серию токенов. Первый токен всегда рассматривается как токен команды (после того, как специальные
@
были удалены и перенаправление перемещено в конец).
- Ведущие разделители токенов перед токеном команды удаляются
- При синтаксическом разборе токена команды
(
действует как разделитель токена команды в дополнение к стандартным разделителям токена
- Обработка последующих токенов зависит от команды.
- Большинство команд просто объединяют все аргументы после токена команды в один токен аргумента. Все разделители токенов аргументов сохраняются. Параметры аргумента обычно не анализируются до фазы 7.
- Особую обработку получают три команды - IF, FOR и REM.
- IF разбивается на две или три отдельные части, которые обрабатываются независимо. Синтаксическая ошибка в конструкции IF приведет к фатальной синтаксической ошибке.
- Операция сравнения - это фактическая команда, которая проходит до фазы 7.
- Все параметры IF полностью анализируются на этапе 2.
- Последовательные разделители токенов сворачиваются в единое пространство.
- В зависимости от оператора сравнения будут идентифицированы один или два токена значений.
- Командный блок True - это набор команд после условия, который анализируется, как и любой другой командный блок. Если нужно использовать ELSE, то блок True должен быть заключен в скобки.
- Необязательный блок команд False - это набор команд после ELSE. Опять же, этот командный блок анализируется нормально.
- Командные блоки True и False не переходят автоматически в последующие фазы. Их последующая обработка контролируется фазой 7.
- FOR разделяется на две части после DO. Синтаксическая ошибка в конструкции FOR приведет к фатальной синтаксической ошибке.
- Часть, проходящая через DO, - это фактическая команда итерации FOR, которая проходит через фазу 7.
- Все параметры FOR полностью разбираются на этапе 2.
- Предложение IN в скобках рассматривается
<LF>
как <space>
. После того, как предложение IN проанализировано, все токены объединяются вместе, чтобы сформировать один токен.
- Последовательные разделители токенов без экранирования и без кавычек сжимаются в единый пробел на протяжении всей команды FOR через DO.
- Часть после DO - это командный блок, который анализируется нормально. Последующая обработка командного блока DO контролируется итерацией на этапе 7.
- REM, обнаруженный в фазе 2, обрабатывается совершенно иначе, чем все другие команды.
- Анализируется только один токен аргумента - парсер игнорирует символы после первого токена аргумента.
- Команда REM может появляться в выводе фазы 3, но команда никогда не выполняется, а исходный текст аргумента отображается эхом - экранирующие вставки не удаляются, за исключением ...
- Если есть только один токен аргумента, который заканчивается неэкранированным
^
, заканчивающим строку, то токен аргумента отбрасывается, а следующая строка анализируется и добавляется к REM. Это повторяется до тех пор, пока не будет больше одного токена или не останется последнего символа ^
.
- Если токен команды начинается с
:
, и это первый раунд фазы 2 (не перезапуск из-за CALL в фазе 6), то
- Токен обычно рассматривается как « Неисполненный ярлык» .
- Остаток строки анализируется, однако
)
, <
, >
, &
и |
больше не имеют особого смысла. Вся оставшаяся часть строки считается частью метки «команда».
- Символ
^
продолжает оставаться особенным, что означает, что продолжение строки может использоваться для добавления следующей строки к метке.
- Неисполненные Метка в скобках блока приведет к неисправимой ошибке синтаксиса , если это не сразу после команды или Выполненная метку на следующей строке.
(
больше не имеет особого значения для первой команды, следующей за ярлыком « Неисполненное» .
- Команда прерывается после завершения анализа метки. Последующие этапы не выполняются для этикетки
- Есть три исключения, которые могут привести к тому, что метка, обнаруженная на этапе 2, будет рассматриваться как выполненная метка , анализ которой продолжается на этапе 7.
- Существует Перенаправление , что предшествует метка фишки, и есть
|
труба или &
, &&
или ||
команда конкатенация на линии.
- Существует перенаправление, которое предшествует токену метки, а команда находится в блоке в скобках.
- Маркер метки - это самая первая команда в строке внутри блока, заключенного в скобки, а приведенная выше строка завершается невыполненной меткой .
- Следующее происходит, когда на этапе 2 обнаруживается
исполненная метка.
- Метка, ее аргументы и перенаправление исключаются из любого вывода эха в фазе 3.
- Все последующие объединенные команды в строке полностью анализируются и выполняются.
- Для получения дополнительной информации о исполненных ярлыках и невыполненных ярлыках см. Https://www.dostips.com/forum/viewtopic.php?f=3&t=3803&p=55405#p55405.
Фаза 3) Эхо проанализированных команд (команд) Только в том случае, если командный блок не начинается с @
, а ECHO был включен в начале предыдущего шага.
Фаза 4) %X
Расширение переменной FOR : только если активна команда FOR и выполняются команды после DO.
- На этом этапе на этапе 1 пакетной обработки переменная FOR, например,
%%X
в %X
. Командная строка имеет другие правила процентного расширения для фазы 1. Это причина того, что командные строки используют, %X
а пакетные файлы используют %%X
переменные FOR.
- Имена переменных FOR чувствительны к регистру, но
~modifiers
не чувствительны к регистру.
~modifiers
имеют приоритет над именами переменных. Если следующий за ним символ ~
является и модификатором, и допустимым именем переменной FOR, и существует следующий символ, который является активным именем переменной FOR, то этот символ интерпретируется как модификатор.
- Имена переменных FOR являются глобальными, но только в контексте предложения DO. Если подпрограмма вызывается из предложения FOR DO, то переменные FOR не раскрываются внутри подпрограммы CALLed. Но если подпрограмма имеет свою собственную команду FOR, то все определенные в настоящее время переменные FOR доступны внутренним командам DO.
- Имена переменных FOR могут быть повторно использованы во вложенных FOR. Внутреннее значение FOR имеет приоритет, но после закрытия INNER FOR восстанавливается внешнее значение FOR.
- Если ECHO был включен в начале этой фазы, то фаза 3) повторяется, чтобы показать проанализированные команды DO после того, как переменные FOR были расширены.
---- С этого момента каждая команда, указанная на этапе 2, обрабатывается отдельно.
---- Фазы с 5 по 7 завершаются для одной команды перед переходом к следующей.
Фаза 5) Отложенное расширение: только если отложенное расширение включено, команда не находится в блоке в скобках по обе стороны канала , и команда не является «голым» пакетным сценарием (имя сценария без круглых скобок, CALL, объединение команд, или труба).
- Каждый токен для команды анализируется на предмет отложенного раскрытия независимо.
- Большинство команд анализируют два или более токена - токен команды, токен аргументов и каждый токен назначения перенаправления.
- Команда FOR анализирует только токен предложения IN.
- Команда IF анализирует только сравнительные значения - одно или два, в зависимости от оператора сравнения.
- Для каждого проанализированного токена сначала проверьте, есть ли он
!
. В противном случае токен не анализируется - это важно для ^
персонажей. Если токен действительно содержит !
, просканируйте каждый символ слева направо:
- Если это каретка (
^
), следующий символ не имеет особого значения, сама каретка удаляется
- Если это восклицательный знак, найдите следующий восклицательный знак (символы вставки больше не наблюдаются), разверните до значения переменной.
- Последовательные открытия
!
сворачиваются в один!
- Все оставшиеся непарные
!
удаляются
- Расширение vars на этом этапе «безопасно», потому что специальные символы больше не обнаруживаются (даже
<CR>
или <LF>
)
- Для более полного объяснения прочтите вторую половину этого из той же ветки dbenham - Фаза восклицательного знака
Фаза 5.3) Обработка конвейера : только если команды находятся по обе стороны канала.
Каждая сторона канала обрабатывается независимо и асинхронно.
- Если команда является внутренней для cmd.exe, или это пакетный файл, или если это заключенный в скобки командный блок, то он выполняется в новом потоке cmd.exe через
%comspec% /S /D /c" commandBlock"
, поэтому командный блок получает фазовый перезапуск, но на этот раз в режиме командной строки.
- Если командный блок заключен в скобки, то все,
<LF>
у кого есть команда до и после, преобразуются в <space>&
. Остальные <LF>
раздеваются.
- Это конец обработки команд канала.
- См. Почему не удается отложенное расширение внутри блока кода, передаваемого по конвейеру? подробнее о разборе и обработке труб
Фаза 5.5) Выполнить перенаправление: теперь выполняется любое перенаправление, обнаруженное на этапе 2.
Фаза 6) Обработка CALL / удвоение каретки: только если токен команды - CALL, или если текст перед первым встречающимся стандартным разделителем токенов - CALL. Если CALL анализируется из более крупного токена команды, то неиспользованная часть добавляется к токену аргументов перед продолжением.
- Просканируйте токен аргументов на предмет отсутствия кавычек
/?
. Если он найден где-либо в пределах жетонов, прервите фазу 6 и перейдите к фазе 7, где будет напечатана СПРАВКА для ЗВОНОК.
- Удалите первый
CALL
, чтобы можно было сложить несколько вызовов CALL
- Удвойте все каретки
- Перезапустите фазы 1, 1.5 и 2, но не переходите к фазе 3.
- Любые удвоенные символы вставки сокращаются до одного символа вставки, если они не заключены в кавычки. Но, к сожалению, кавычки остаются удвоенными.
- Фаза 1 немного меняется
- Ошибки расширения на шаге 1.2 или 1.3 прерывают CALL, но ошибка не является фатальной - пакетная обработка продолжается.
- Задачи фазы 2 немного изменены
- Любое вновь появившееся перенаправление без кавычек, неэкранированное перенаправление, которое не было обнаружено в первом раунде фазы 2, обнаруживается, но удаляется (включая имя файла) без фактического выполнения перенаправления.
- Любой вновь появившийся в конце строки неэкранированный курсор без кавычек удаляется без продолжения строки.
- ВЫЗОВ прерывается без ошибок, если обнаруживается что-либо из следующего
- Новое появление без кавычек, без экранирования
&
или|
- Результирующий токен команды начинается с без кавычек, без экранирования.
(
- Самый первый токен после удаленного CALL начинается с
@
- Если в результате команды, казалось бы , действует IF или FOR, то выполнение будет впоследствии терпеть неудачу с ошибкой о том , что
IF
или FOR
не признается в качестве внутренней или внешней команды.
- Конечно, CALL не прерывается во втором раунде фазы 2, если полученный токен команды является меткой, начинающейся с
:
.
- Если полученный токен команды - CALL, перезапустите Фазу 6 (повторяется до тех пор, пока CALL не перестанет)
- Если результирующий токен команды является пакетным сценарием или меткой:, то выполнение CALL полностью обрабатывается оставшейся частью фазы 6.
- Поместите текущую позицию файла пакетного сценария в стек вызовов, чтобы выполнение могло возобновиться с правильной позиции после завершения CALL.
- Настройте токены аргументов% 0,% 1,% 2, ...% N и% * для CALL, используя все результирующие токены
- Если токен команды - это метка, начинающаяся с
:
, то
- Фаза перезапуска 5. Это может повлиять на то, что: метка вызывается. Но поскольку токены% 0 и т. Д. Уже настроены, он не изменит аргументы, передаваемые в процедуру CALLed.
- Выполните метку GOTO, чтобы поместить указатель файла в начало подпрограммы (игнорируйте любые другие токены, которые могут следовать за меткой:). Правила работы GOTO см. В Этапе 7.
- Иначе передать управление указанному пакетному сценарию.
- Выполнение метки CALLed: или сценария продолжается до тех пор, пока не будет достигнут EXIT / B или конец файла, после чего стек CALL выталкивается и выполнение возобновляется с сохраненной позиции файла.
Фаза 7 не выполняется для сценариев CALLed или меток:.
- В противном случае результат фазы 6 попадает в фазу 7 для выполнения.
Фаза 7) Выполнить: команда выполняется.
- 7.1 - Выполнить внутреннюю команду - Если токен команды заключен в кавычки, пропустите этот шаг. В противном случае попытайтесь разобрать внутреннюю команду и выполнить.
- Чтобы определить, представляет ли токен команды без кавычек внутреннюю команду, выполняются следующие тесты:
- Если токен команды точно соответствует внутренней команде, выполните ее.
- Иначе сломайте токен команды перед первым вхождением
+
/
[
]
<space>
<tab>
,
;
или =
Если предыдущий текст является внутренней командой, запомните эту команду
- Если в режиме командной строки, или если команда из блока в скобках, IF true или false, командный блок, FOR DO командный блок или задействована в конкатенации команд, выполните внутреннюю команду
- В противном случае (должна быть автономной командой в пакетном режиме) сканировать текущую папку и путь к файлу .COM, .EXE, .BAT или .CMD, базовое имя которого совпадает с исходным токеном команды.
- Если первым совпадающим файлом является .BAT или .CMD, перейдите к 7.3.exec и выполните этот сценарий.
- В противном случае (совпадение не найдено или первое совпадение .EXE или .COM) выполнить запомненную внутреннюю команду
- В
противном случае прервите токен команды перед первым вхождением
.
\
или :
Если предыдущий текст не является внутренней командой, то перейдите к 7.2.
Иначе предыдущий текст может быть внутренней командой. Запомните эту команду.
- Разорвать токен команды перед первым вхождением
+
/
[
]
<space>
<tab>
,
;
или. =
Если предыдущий текст - это путь к существующему файлу, то перейти к 7.2.
Иначе выполнить запомненную внутреннюю команду.
- Если внутренняя команда анализируется из более крупного токена команды, то неиспользуемая часть токена команды включается в список аргументов.
- Тот факт, что токен команды анализируется как внутренняя команда, не означает, что он будет выполнен успешно. У каждой внутренней команды есть свои правила относительно того, как анализируются аргументы и параметры, а также какой синтаксис разрешен.
- Все внутренние команды будут печатать справку вместо выполнения своей функции, если
/?
обнаружены. Большинство узнает, /?
появляется ли это где-нибудь в аргументах. Но некоторые команды, такие как ECHO и SET, выводят справку только в том случае, если первый токен аргумента начинается с /?
.
- SET имеет интересную семантику:
- Если в команде SET перед именем переменной стоит кавычка и включены расширения
set "name=content" ignored
-> значение =, content
тогда текст между первым знаком равенства и последней кавычкой используется в качестве содержимого (первая равная и последняя кавычки исключены). Текст после последней цитаты игнорируется. Если после знака равенства нет кавычек, то остальная часть строки используется как содержимое.
- Если в команде SET нет кавычек перед именем
set name="content" not ignored
-> value =, "content" not ignored
тогда вся оставшаяся часть строки после равенства используется в качестве содержимого, включая все кавычки, которые могут присутствовать.
- Оценивается сравнение IF, и в зависимости от того, является ли условие истинным или ложным, соответствующий уже проанализированный зависимый командный блок обрабатывается, начиная с фазы 5.
- Предложение IN команды FOR повторяется соответствующим образом.
- Если это FOR / F, который повторяет вывод командного блока, то:
- Предложение IN выполняется в новом процессе cmd.exe через CMD / C.
- Командный блок должен пройти весь процесс синтаксического анализа второй раз, но на этот раз в контексте командной строки.
- ECHO запускается, и отложенное расширение обычно запускается отключенным (в зависимости от настройки реестра)
- Все изменения среды, сделанные с помощью командного блока предложения IN, будут потеряны после завершения дочернего процесса cmd.exe.
- Для каждой итерации:
- Значения переменной FOR определены
- Затем уже проанализированный командный блок DO обрабатывается, начиная с фазы 4.
- GOTO использует следующую логику для поиска метки:
- Метка извлекается из токена первого аргумента
- Скрипт сканируется на предмет следующего появления метки
- Сканирование начинается с текущей позиции файла
- Если достигается конец файла, сканирование возвращается к началу файла и продолжается до исходной начальной точки.
- Сканирование останавливается при первом вхождении найденной метки, и указатель файла устанавливается на строку, следующую сразу за меткой. Выполнение скрипта возобновляется с этого момента. Обратите внимание, что успешный истинный GOTO немедленно прервет любой проанализированный блок кода, включая циклы FOR.
- Если метка не найдена или токен метки отсутствует, GOTO завершается ошибкой, печатается сообщение об ошибке и открывается стек вызовов. Это эффективно работает как EXIT / B, за исключением того, что любые уже проанализированные команды в текущем командном блоке, следующие за GOTO, все еще выполняются, но в контексте CALLer (контекст, который существует после EXIT / B)
- См. Https://www.dostips.com/forum/viewtopic.php?f=3&t=3803 для более точного описания правил, используемых для синтаксического анализа меток.
- И RENAME, и COPY принимают подстановочные знаки для исходного и целевого путей. Но Microsoft делает ужасную работу, документируя, как работают подстановочные знаки, особенно для целевого пути. Полезный набор правил подстановки можно найти в разделе Как команда Windows RENAME интерпретирует подстановочные знаки?
- 7.2 - Выполнить изменение громкости - Иначе, если токен команды не начинается с кавычки, имеет длину ровно два символа, а второй символ - двоеточие, измените громкость
- Все токены аргументов игнорируются
- Если объем, указанный первым символом, не может быть найден, отменить с ошибкой.
- Маркер команды
::
всегда будет приводить к ошибке, если только SUBST не используется для определения тома. ::
Если SUBST используется для определения тома ::
, то том будет изменен, он не будет рассматриваться как метка.
- 7.3 - Выполнить внешнюю команду - Иначе попробуйте обработать команду как внешнюю команду.
- Если в режиме командной строки и командах не котируются и не начинается с описанием объема, белое пространством,
,
, ;
, =
или +
затем перерыв команды лексемы при первом появлении <space>
,
;
или =
и предварять остаток к аргументу маркеров (ов).
- Если 2-й символ токена команды является двоеточием, убедитесь, что можно найти объем, указанный 1-м символом.
Если том не может быть найден, прервите операцию с ошибкой.
- Если в пакетном режиме и токен команды начинается с
:
, то перейти к 7.4.
Обратите внимание, что если токен метки начинается с ::
, то это не будет достигнуто, потому что предыдущий шаг будет прерван с ошибкой, если SUBST не используется для определения тома для ::
.
- Определите внешнюю команду для выполнения.
- Это сложный процесс, который может включать текущий том, текущий каталог, переменную PATH, переменную PATHEXT и / или ассоциации файлов.
- Если действительная внешняя команда не может быть идентифицирована, прервать выполнение с ошибкой.
- Если в режиме командной строки и токен команды начинается с
:
, то перейти к 7.4.
Обратите внимание, что это редко достигается, потому что предыдущий шаг будет прерван с ошибкой, если токен команды не начинается с ::
, и SUBST используется для определения тома для ::
, а весь токен команды является допустимым путем к внешней команде.
- 7.3.exec - выполнить внешнюю команду.
- 7.4 - Игнорировать метку - игнорировать команду и все ее аргументы, если маркер команды начинается с
:
.
Правила 7.2 и 7.3 могут помешать метке достичь этой точки.
Парсер командной строки:
Работает аналогично BatchLine-Parser, за исключением:
Фаза 1) Процентное расширение:
- Нет
%*
и %1
т. Д. Расширение аргумента
- Если var не определен, то
%var%
остается без изменений.
- Никакой специальной обработки
%%
. Если var = content, %%var%%
заменяется на %content%
.
Фаза 3) Эхо проанализированных команд
- Это не выполняется после фазы 2. Это выполняется только после фазы 4 для командного блока FOR DO.
Фаза 5) Отложенное расширение: только если отложенное расширение включено
- Если var не определен, то
!var!
остается без изменений.
Фаза 7) Выполнить команду
- Попытки ВЫЗВАТЬ или НАЙТИ a: label приводят к ошибке.
- Как уже было задокументировано на этапе 7, выполненная метка может привести к ошибке в различных сценариях.
- Этикетки, выполняемые в пакетном режиме, могут вызвать ошибку, только если они начинаются с
::
- Выполненные в командной строке метки почти всегда приводят к ошибке
Разбор целочисленных значений
Существует много разных контекстов, в которых cmd.exe анализирует целочисленные значения из строк, а правила несовместимы:
SET /A
IF
%var:~n,m%
(расширение переменной подстроки)
FOR /F "TOKENS=n"
FOR /F "SKIP=n"
FOR /L %%A in (n1 n2 n3)
EXIT [/B] n
Подробную информацию об этих правилах можно найти в разделе «Правила анализа чисел CMD.EXE».
Для всех, кто желает улучшить правила синтаксического анализа cmd.exe, на форуме DosTips есть тема для обсуждения, где можно сообщить о проблемах и внести предложения.
Надеюсь, это поможет
Ян Эрик (jeb) - оригинальный автор и первооткрыватель фаз
Дэйв Бенхэм (dbenham) - много дополнительного контента и редактирования