Сначала откройте окно командной строки, запустите set /?
и прочитайте всю справочную информацию по команде SET на нескольких страницах.Это объясняет использование отложенное расширение на IF и FOR примере.
Скорее всего, было бы также полезно прочитать ответыon:
Как интерпретатор сценариев Windows Command Interpreter (CMD.EXE) анализирует?
Ваш пакетный файл содержит setlocal enabledelayedexpansion
вверху, чтобы включить отложенное расширение переменной среды.Но ни на одну переменную среды не ссылаются с синтаксисом !VariableName!
, чтобы действительно использовать отложенное расширение переменной среды.По этой причине "%Element%"
модифицируется командным процессором Windows уже при разборе всего блока команд, начиная с (
и заканчивая сопоставлением )
с ""
перед выполнением команды FOR .Переменная окружения Element
не определена до достижения командной строки FOR и cmd.exe
анализирует всю командную строку FOR с блоком команд, заканчивающимся на )
в конце пакетафайл перед выполнением FOR .
CALL в основном используется для вызова подпрограммы или другого пакетного файла из пакетного файла.Использование CALL в простой командной строке может использоваться для получения командной строки, дважды проанализированной командным процессором Windows, во избежание использования отложенного расширения.В первых трех строках SET абсолютно не обязательно использовать CALL , так как при повторном разборе командных строк SET ничего не меняется.
Первое решение - без использования отложенного расширения с помощью CALL для двойного анализа двух командных строк в блоке кода.
@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "ListOFElts[0]=First"
set "ListOFElts[1]=Second"
set "ListOFElts[2]=Third"
for /L %%I in (0,1,2) do (
call set "Element=%%ListOFElts[%%I]%%"
call %SystemRoot%\System32\whoami.exe /groups /fo list | %SystemRoot%\System32\find.exe "%%Element%%"
)
endlocal
Определение переменной среды Element
не обязательно в командеблок как его значение ссылается только один раз.Таким образом, более компактным и, следовательно, более быстрым выполнением будет:
@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "ListOFElts[0]=First"
set "ListOFElts[1]=Second"
set "ListOFElts[2]=Third"
for /L %%I in (0,1,2) do call %SystemRoot%\System32\whoami.exe /groups /fo list | %SystemRoot%\System32\find.exe "%%ListOFElts[%%I]%%"
endlocal
Больше нет командного блока для выполнения с помощью FOR на каждой итерации цикла, только одна командная строка.Но тем не менее необходимо использовать команду CALL и использовать %%ListOFElts[%%I]%%
, поскольку вся командная строка FOR уже проанализирована для ссылок %VariableName%
перед выполнением FOR первый раз.Таким образом, "%ListOFElts[%%I]%"
будет заменено уже на ""
до того, как FOR будет вообще выполнено.
Третье решение - использование действительно отложенного расширения.Решение является компактной версией с использованием отложенного расширения, которое аналогично примеру вывода FOR с помощью команды SET :
@echo off
setlocal EnableExtensions EnableDelayedExpansion
set "ListOFElts[0]=First"
set "ListOFElts[1]=Second"
set "ListOFElts[2]=Third"
for /L %%I in (0,1,2) do %SystemRoot%\System32\whoami.exe /groups /fo list | %SystemRoot%\System32\find.exe "!ListOFElts[%%I]!"
endlocal
Команда FINDSTR позволяет указывать несколько строк поиска.
@%SystemRoot%\System32\whoami.exe /groups /fo list | %SystemRoot%\System32\findstr.exe /L /C:"First" /C:"Second" /C:"Third"
FINDSTR выводит все строки из входного потока, содержащего любую из трех буквенно-чувствительных к регистру интерпретируемых строк, указанных в /C:"..."
,Эта единственная командная строка в командном файле заменяет все четыре вышеуказанных командных файла.
Чтобы понять используемые команды и их работу, откройте окно командной строки, выполните там следующие команды и полностью прочитайте все отображаемые страницы справки.для каждой команды очень тщательно.
call /?
echo /?
endlocal /?
find /?
findstr /?
for /?
set /?
setlocal /?
whoami /?
См.также ответьте на Почему нет строкового вывода с 'echo% var%' после использования 'set var = text' в командной строке? для подробного объяснения, почему на всех SET командных строках "variable=value"
используется вместо variable=value
в пакетных файлах выше.