Командный процессор Windows заменяет все вхождения %variable%
в командном блоке, начиная с (
и заканчивая сопоставлением )
текущим значением указанной переменной среды перед выполнением команды с помощью команды блок. См. Как анализирует сценарии интерпретатора команд Windows (CMD.EXE)? Эту обработку блока команд с помощью cmd.exe
можно увидеть, запустив пакетный файл из окна командной строки вместо двойного щелчка по пакету. файл с @echo off
удален или изменен на @echo ON
или закомментирован временно, пока пакетный файл не работает должным образом.
Вывод справки при запуске set /?
в окне командной строки объясняет на примере IF и FOR , когда и как использовать отложенное расширение , которое является предпочтительным способом доступа к значению переменной среды в пределах командного блока, определяемого или изменяемого в том же командном блоке.
Другое решение - ссылка на переменную среды с использованием синтаксиса %%variable%%
и использование команды CALL для принудительного двойного анализа этой командной строки с помощью cmd.exe
. В этом случае %%
изменяется при разборе всего командного блока на %
с обеих сторон указанной переменной среды, а затем при выполнении команды CALL оставшиеся %variable%
анализируются еще раз и заменяются на текущее значение указанной переменной.
В разнесенном коде партии переменная окружения str
не определена выше FOR командная строка с блоком команд. По этой причине echo %str% >> names.txt
выполняет синтаксический анализ всего командного блока, измененного с cmd.exe
на echo >> names.txt
до того, как FOR будет выполнен вообще, и поэтому ECHO просто выводит три раза текущее состояние .
Также командная строка call set str=%%str:Name=%word%%%
не работает, поскольку word
не определена ранее FOR командной строки с блоком команд и, следовательно, %word%
уже заменена ничем, что приводит к командной строке call set str=%str:Name=%
окончательно выполняется три раза при выполнении цикла.
Следующая ошибка - использование опции FOR /L
для этого цикла. Вывод справки при запуске for /?
в окне командной строки объясняет для for /L
:
FOR /L %variable IN (start,step,end) DO command [command-parameters]
The set is a sequence of numbers from start to end, by step amount.
So (1,1,5) would generate the sequence 1 2 3 4 5 and (5,-1,1) would
generate the sequence (5 4 3 2 1)
После прочтения этой справки должно быть ясно, что /L
не подходит для этой задачи.
Следующая ошибка заключается в том, что подстановки строк, выполняемые с помощью команды SET или непосредственно с помощью cmd.exe
при разборе командной строки, всегда применяются без учета регистра. Строка, присвоенная переменной окружения str
, содержит name
и Name
, которые заменяются при подстановке строки. Это действительно не нужно здесь.
Тогда есть большая разница при использовании set variable="value"
или при использовании set "variable=value"
. Последнее лучше, как подробно объяснено в ответе на Почему нет строкового вывода с 'echo% var%' после использования 'set var = text' в командной строке?
Наконец, пробел, оставленный оператору перенаправления >>
, также выводится командой ECHO , что приводит к завершающему пробелу в файле. Поэтому оператор перенаправления >>
не должен отделяться пробелом от строки для записи в файл.
Первый рабочий код для примера использует отложенное расширение переменной среды:
@echo off
setlocal EnableExtensions EnableDelayedExpansion
del names.txt 2>nul
set "str=My name is #name#"
for %%I in (Veronica, Nils, Mike, Tom) do echo !str:#name#=%%~I!>>names.txt
endlocal
Второй рабочий код для примера использует трюк CALL :
@echo off
del names.txt 2>nul
set "str=My name is #name#"
for %%I in (Veronica, Nils, Mike, Tom) do call echo %%str:#name#=%%~I%%>>names.txt
Чтобы понять используемые команды и то, как они работают, откройте окно командной строки, выполните там следующие команды и полностью прочитайте все страницы справки, отображаемые для каждой команды.
call /?
del /?
echo /?
endlocal /?
for /?
setlocal /?
set /?
См. Также статью Microsoft о Использование операторов перенаправления команд .