Почему FOR терпит неудачу с задержкой раскрытия подстроки после IN? - PullRequest
0 голосов
/ 17 мая 2018

Расширение подстроки работает в пределах набора for цикла (то есть части в скобках после in), когда используется немедленное расширение (запишите %%I вместо %I в пакетном файле):

set "X=123"
for %I in (%X:~1,1%) do @echo %I

Однако происходит сбой при применении отложенного расширения:

for %I in (!X:~1,1!) do @echo %I

Я ожидаю, что результат будет:

2

Но вместо этого это:

!X:~1
1!

Почему это так и как я могу предотвратить это?

Я знаю, что мог бы обойти это, цитируя набор и используя ~, но это не то, что я хочу здесь:

for %I in ("!X:~1,1!") do @echo %~I

Сбой следующей командной строки:

for %I in (!X:*2=!) do @echo %I

Неожиданный вывод:

!

Кроме того, for командные строки с использованием переключателей /R, /L и /R не работают с таким синтаксисом подстроки.

Это, безусловно, связано с тем, что , и = являются разделителями токенов для cmd, так же как SPACE , TAB , ; и т. д.

1 Ответ

0 голосов
/ 22 мая 2018

В соответствии с темой Как интерпретатор сценариев команд Windows (CMD.EXE) анализирует сценарии? , а также многочисленные комментарии здесь ответ лежит в особым образом for анализируются петли.

Ключом является следующая выдержка из этого ответа (см., В частности, курсив ):

Этап 2) Обработка специальных символов, токенизация и создание кэшированного блока команд:
[...]

  • Три команды получают специальную обработку - IF, FOR и REM
    [...]
    • FOR делится на две после DO. Синтаксическая ошибка в конструкции FOR приведет к фатальной синтаксической ошибке.
    • Часть через DO является фактической итерационной командой FOR, которая проходит всю фазу 7
      • Все опции FOR полностью анализируются в фазе 2.
      • В скобках IN содержится <LF> как <space>. После разбора предложения IN все токены объединяются в один токен.
      • Последовательные разделители токенов сворачиваются в один пробел по всей команде FOR через DO.

Из-за того, что после синтаксического анализа for происходит задержанное расширение, и описанного поведения разделители токенов, такие как SPACE , TAB , ,, ;, = и т. Д. Преобразуются в один SPACE , следовательно, выражение расширения подстроки, например !X:~1,1!, изменяется на !X:~1 1!, а выражение подстроки подстановки, например !X:*2=!, изменяется на !X:*2 !, оба синтаксиса неверны.

Поэтому, чтобы решить эту проблему, вам нужно экранировать токены с помощью ^ вроде:

for %I in (!X:~1^,1!) do @echo %I

и

for %I in (!X:*2^=!) do @echo %I

(Кстати, есть очень похожая проблема с if утверждениями .)

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