Ми провели експерименти з вивчення граматики пакетних сценаріїв. Ми також досліджували відмінності між режимом пакетного та командного рядка.
Аналіз пакетної лінії:
Ось короткий огляд фаз в аналізаторі рядків пакетного файлу:
Фаза 0) Рядок читання:
Фаза 1) Процентне розширення:
Фаза 2) Обробляйте спеціальні символи, токенізуйте та будуйте кешований блок команд: Це складний процес, на який впливають такі речі, як цитати, спеціальні символи, роздільники маркерів та втечі карети.
Фаза 3) Відгуки команд, що розбираються, лише якщо командний блок не починався з @
, а ECHO був увімкнено на початку попереднього кроку.
Фаза 4) ДЛЯ %X
змінної розширення: Тільки якщо команда FOR активна і команди після DO обробляються.
Фаза 5) Затримка розширення: Тільки якщо ввімкнено затримку розширення
Фаза 5.3) Обробка труб: Тільки якщо команди знаходяться з обох боків труби
Фаза 5.5) Виконати перенаправлення:
Фаза 6) Обробка CALL / подвоєння карети: Тільки якщо маркер команди CALL
Фаза 7) Виконати: команда виконується
Ось деталі для кожної фази:
Зауважимо, що описані нижче фази є лише моделлю того, як працює парний аналізатор. Фактичні внутрішні cmd.exe можуть не відображати ці фази. Але ця модель ефективна при прогнозуванні поведінки пакетних сценаріїв.
Фаза 0) Рядок читання: Прочитайте рядок введення через перший <LF>
.
- Під час читання рядка, який слід проаналізувати як команду,
<Ctrl-Z>
(0x1A) читається як <LF>
(LineFeed 0x0A)
- Коли GOTO або CALL читає рядки під час сканування на: label,,
<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>
, то він трактується як буквальний, тобто цей процес не є рекурсивним.
- Unescaped
<LF>
не в дужках
<LF>
знімається і аналіз поточного рядка припиняється.
- Будь-які символи в буфері рядків просто ігноруються.
- Немає
<LF>
в межах блоку FOR IN
<LF>
перетворюється в <space>
- Якщо в кінці буфера рядка, то наступний рядок зчитується і додається до поточного.
- Немає
<LF>
в межах командного блоку
<LF>
перетворюється в <LF><space>
, і the <space>
обробляється як частина наступного рядка командного блоку.
- Якщо в кінці буфера рядка, наступний рядок читається і додається до пробілу.
- Якщо один із спеціальних символів
&
|
<
або >
, розділіть рядок у цій точці для того, щоб обробляти труби, конкатенацію команд та перенаправлення.
- У випадку з трубою (
|
) кожна сторона є окремою командою (або командним блоком), яка отримує спеціальну обробку на фазі 5.3
- У разі
&
, &&
чи ||
команда конкатенації, кожна сторона конкатенації розглядаються в якості окремої команди.
- У разі
<
, <<
, >
або >>
перенаправлення, положення перенаправлення аналізується, тимчасово вилучено, а потім додається до кінця поточної команди. Застереження про переадресацію складається з необов'язкової цифри обробки файлу, оператора перенаправлення та маркера призначення перенаправлення.
- Якщо маркер, що передує оператору переадресації, є однією незміщеною цифрою, то цифра визначає ручку файлу, яку слід перенаправити. Якщо маркер ручки не знайдено, то виведіть значення переспрямування за замовчуванням на 1 (stdout), а вхідні параметри перенаправлення - на 0 (stdin).
- Якщо найперший жетон для цієї команди (до переміщення перенаправлення до кінця) починається з
@
, це @
має особливе значення. ( @
не є особливим у будь-якому іншому контексті)
- Спеціальний
@
знімається.
- Якщо ECHO увімкнено, то ця команда разом з будь-якими наступними об'єднаними командами у цьому рядку виключаються із луни фази 3. Якщо
@
до початку відкриття (
, то весь дужок блоку виключається з луни фази 3.
- Круглі дужки процесу (передбачає складені оператори у кількох рядках):
- Якщо аналізатор не шукає маркер команди, то
(
він не є спеціальним.
- Якщо аналізатор шукає маркер команди і знаходить
(
, тоді запустіть нове складене оператор і збільште лічильник дужок
- Якщо лічильник круглих дужок дорівнює> 0, то
)
припиняє складене твердження і зменшує лічильник дужок.
- Якщо кінець рядка досягнуто і лічильник дужок дорівнює> 0, наступний рядок буде доданий до складеного оператора (починається знову з фази 0)
- Якщо лічильник круглих дужок дорівнює 0, і аналізатор шукає команду, то
)
функціонує аналогічно REM
оператору, доки за ним негайно слідує роздільник обмежень, спеціальний символ, новий рядок або кінець файлу.
- Усі спеціальні символи втрачають значення, за винятком
^
(можливе конкатенація рядків)
- Після досягнення кінця логічного рядка вся "команда" відкидається.
- Кожна команда розбирається на серію лексем. Перший маркер завжди трактується як командний маркер (після спеціального
@
зняття та перенаправлення переміщеного до кінця).
- Провідні роздільники токенів перед командним маркером знімаються
- Під час розбору токена команди, він
(
функціонує як роздільник обмежень маркера на додаток до стандартних роздільників токенів
- Обробка наступних жетонів залежить від команди.
- Більшість команд просто об'єднує всі аргументи після маркера команди в один маркер аргументу. Усі роздільники маркера аргументів збережені. Параметри аргументів зазвичай не розбираються до 7 фази.
- Три команди отримують спеціальну обробку - IF, FOR і REM
- ЯКЩО розділяється на дві або три чіткі частини, які обробляються незалежно. Помилка синтаксису в конструкції 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 активна і команди після DO обробляються.
- На даний момент, фаза 1 пакетної обробки буде вже перетворена для змінних , як
%%X
в %X
. Командний рядок має різні відсоткові правила розширення для фази 1. Це причина використання командних рядків, %X
але пакетні файли використовують %%X
для змінних FOR.
- Для імен змінних чутливі регістри, але
~modifiers
вони не відрізняються від регістру.
~modifiers
мати перевагу над іменами змінних. Якщо наступний символ ~
є і модифікатором, і дійсним ім'ям змінної FOR, і існує наступний символ, який є активним іменем змінної FOR, тоді символ інтерпретується як модифікатор.
- Імена змінних FOR глобальні, але лише в контексті пункту DO. Якщо рутина CALLED з пункту FOR DO, змінні FOR не розширюються в межах CALLED. Але якщо у рутини є своя команда FOR, то всі визначені в даний час змінні FOR доступні для внутрішніх команд DO.
- Імена змінних FOR можуть бути повторно використані в межах вкладених FOR. Внутрішнє значення FOR має перевагу, але як тільки ВНУТРІШНЯ 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, де буде надруковано HELP for CALL.
- Видаліть перше
CALL
, тож декілька CALL можна скласти
- Подвійні всі грифи
- Перезапустіть фази 1, 1.5 та 2, але не продовжуйте фазу 3
- Будь-які подвійні піклування зводяться назад до однієї карети до тих пір, поки вони не цитуються. Але, на жаль, котируються роботи залишаються вдвічі.
- Фаза 1 трохи змінюється
- Помилки розширення на кроках 1.2 або 1.3 скасовують CALL, але помилка не є фатальною - пакетна обробка продовжується.
- Завдання Фази 2 трохи змінені
- Буде виявлено будь-яке нещодавно з'явилося некотируване, несказоване перенаправлення, яке не було виявлено у першому етапі 2 фази, але воно видаляється (включаючи ім'я файлу), фактично не виконуючи перенаправлення
- Будь-яка щойно з’явилася без котирувальної, немальована каре в кінці рядка видаляється, не виконуючи продовження рядка
- CALL припиняється без помилок, якщо виявлено що-небудь з наступного
- Щойно з’являються без котирувань, без назви
&
або|
- Отриманий маркер команди починається з без котирування, без націлювання
(
- Перший жетон після видаленого CALL розпочався з
@
- Якщо в результаті команди, здавалося б , діє IF або FOR, то виконання буде згодом зазнати невдач з помилкою про те , що
IF
або FOR
не зізнається в якості внутрішньої чи зовнішньої команди.
- Звичайно, CALL не припиняється в цьому 2-му раунді фази 2, якщо отриманий командний маркер є міткою, що починається з
:
.
- Якщо результуючий маркер команди CALL, перезапустіть Фазу 6 (повторюється, поки не буде більше CALL)
- Якщо результуючий командний маркер - це пакетний скрипт або мітка:, виконання CALL повністю обробляється залишком етапу 6.
- Натисніть на поточну позицію файлу сценарію файлу на стеку викликів, щоб виконання моменту відновилося з правильної позиції, коли CALL завершено.
- Установіть аргументи% 0,% 1,% 2, ...% N та% * для CALL, використовуючи всі результуючі лексеми
- Якщо командний маркер - це мітка, яка починається з
:
, тоді
- Фаза перезапуску 5. Це може вплинути на що: мітка CALLED. Але оскільки символи% 0 тощо вже налаштовані, це не змінить аргументів, переданих у процедуру CALLED.
- Виконайте мітку GOTO, щоб розташувати вказівник на файл на початку підпрограми (ігноруйте будь-які інші лексеми, які можуть слідувати за: label) Дивіться Фазу 7 щодо правил роботи GOTO.
- Інше управління передачею у вказаний пакетний сценарій.
- Виконання мітки або сценарію CALLed продовжується до тих пір, поки не буде досягнуто EXIT / B або кінця файлу, після чого буде вискакуватися стек CALL і виконання відновиться зі збереженого положення файлу.
Фаза 7 не виконується для CALLED-скриптів або: міток.
- Крім того, результат 6 фази переходить у фазу 7 для виконання.
Фаза 7) Виконати: команда виконується
- 7.1 - Виконати внутрішню команду - Якщо маркер команди цитується, пропустіть цей крок. В іншому випадку спробуйте розібрати внутрішню команду та виконати.
- Наступні тести робляться, щоб визначити, чи маркер команди без котирування являє собою внутрішню команду:
- Якщо маркер команди точно відповідає внутрішній команді, виконайте її.
- Ще розбийте маркер команди перед першим появою
+
/
[
]
<space>
<tab>
,
;
або =
Якщо попередній текст є внутрішньою командою, то запам'ятайте цю команду
- Якщо в режимі командного рядка або якщо команда є з круглого блоку, якщо БЕЗПОЛЬЗОВИЙ або хибний блок команд, Блок команд ДЛО ДО або пов'язаний з об'єднанням команд, виконайте внутрішню команду
- В іншому (має бути окрема команда в пакетному режимі) скануйте поточну папку та PATH на файл .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
-> value =, content
тоді текст між першим знаком рівності та останньою цитатою використовується як вміст (перша рівна та остання цитата виключена). Текст після останньої цитати ігнорується. Якщо після знака рівності немає лапки, то решта рядка використовується як зміст.
- Якщо команда SET не має лапки перед назвою
set name="content" not ignored
-> value =, "content" not ignored
тоді весь залишок рядка після рівного використовується як вміст, включаючи будь-які та всі лапки, які можуть бути присутніми.
- Оцінюється порівняння IF, і залежно від того, чи умова істинна чи помилкова, обробляється відповідний вже проаналізований залежний командний блок, починаючи з фази 5.
- Пункт IN команди переведено відповідним чином.
- Якщо це FOR / F, який ітералізує вихід командного блоку, то:
- Становище IN виконується в новому процесі cmd.exe через CMD / C.
- Командний блок повинен пройти весь процес розбору вдруге, але цього разу в контексті командного рядка
- ECHO почне ВКЛЮЧЕНО, і затримка розширення зазвичай починається відключена (залежно від налаштування реєстру)
- Усі зміни середовища, внесені командним блоком пункту IN, будуть втрачені після завершення процесу дочірнього cmd.exe
- Для кожної ітерації:
- Визначені значення змінних FOR
- Потім вже проаналізований блок команд DO обробляється, починаючи з фази 4.
- GOTO використовує таку логіку, щоб знайти: label
- Мітка аналізується з першого маркера аргументу
- Сценарій сканується для наступного появи мітки
- Сканування починається з поточного положення файлу
- Якщо кінець файлу досягнуто, то сканування повертається до початку файлу і продовжується до початкової початкової точки.
- Сканування припиняється при першому появі знайденої мітки, і вказівник файлу встановлюється на рядок, що знаходиться безпосередньо за міткою. Виконання сценарію поновлюється з цього моменту. Зауважте, що успішний справжній 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>
,
;
або =
й випереджала залишок до аргументу маркерів (ів).
- Якщо другий символ командного маркера є двокрапкою, то перевірте, чи може бути знайдений том, визначений 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 = вміст, то %%var%%
розгортається до %content%
.
Фаза 3) Відлуння проаналізованих команд
- Це не виконується після фази 2. Вона виконується лише після фази 4 для блоку команд FOR DO.
Фаза 5) Затримка розширення: лише якщо ввімкнено DelayedExpansion
- Якщо var не визначено, він
!var!
залишається незмінним.
Фаза 7) Виконати команду
- Спроби CALL або GOTO 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) - багато додаткового вмісту та редагування