我有一个字符串元素列表。
setlocal enabledelayedexpansion
CALL SET ListOFElts[0]=First
CALL SET ListOFElts[1]=Second
CALL SET ListOFElts[2]=Third
for /l %%n in (0,1,3) do (
CALL SET Element=%%ListOFElts[%%n]%%
whoami /groups /fo list | find "%Element%"
)
我想尝试使用命令find
查找每个元素,但变量Element
似乎没有“被识别”。当我尝试这个时,它不会为Element
变量输出任何内容:
setlocal enabledelayedexpansion
CALL SET ListOFElts[0]=First
CALL SET ListOFElts[1]=Second
CALL SET ListOFElts[2]=Third
for /l %%n in (0,1,3) do (
CALL SET Element=%%ListOFElts[%%n]%%
whoami /groups /fo list | find ""
)
-
我也尝试过:
whoami /groups /fo list | find "%%Element%%"
上一行的输出:
whoami /groups /fo list | find "%Element%"
-
然后我尝试了(使用setlocal enabledelayedexpansion
):
whoami /groups /fo list | find "!Element!"
上一行的输出:
whoami /groups /fo list | find "!Element!"
-
我想得到这个(例如第一个循环):
whoami /groups /fo list | find "First"
感谢您的协助。
答案 0 :(得分:0)
我最好的猜测:
@Echo Off
Set "ListOfElts[0]=First"
Set "ListOfElts[1]=Second"
Set "ListOfElts[2]=Third"
For /F "Tokens=1* Delims==" %%A In ('Set ListOfElts[ 2^>Nul'
) Do WhoAmI /GROUPS /FO LIST | Find /I "%%~B"
Pause
答案 1 :(得分:0)
首先,打开一个命令提示符窗口,运行set /?
并在几个页面上读取命令 SET 的整个帮助输出。它解释了delayed expansion在 IF 和 FOR 示例中的用法。
阅读答案很可能也很有帮助:
How does the Windows Command Interpreter (CMD.EXE) parse scripts?
您的批处理文件在顶部包含setlocal enabledelayedexpansion
,以启用延迟的环境变量扩展。但是没有使用语法!VariableName!
引用环境变量来真正利用延迟的环境变量扩展。因此,在执行命令之前,Windows命令处理器已经解析"%Element%"
已经解析整个命令块,从(
开始,到匹配)
到""
。 FOR 即可。在达到 FOR 命令行之前未定义环境变量Element
,并且cmd.exe
使用以{结尾的命令块解析整个 FOR 命令行{1}}在执行 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
在每次循环迭代中,只有一个命令行, FOR 不再执行命令块。但是仍然需要使用命令 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 %SystemRoot%\System32\whoami.exe /groups /fo list | %SystemRoot%\System32\find.exe "%%ListOFElts[%%I]%%"
endlocal
,因为在执行%%ListOFElts[%%I]%%引用解析了整个 FOR 命令行> FOR 第一次。因此,在 FOR 执行之前,%VariableName%
已被替换为"%ListOFElts[%%I]%"
。
第三种解决方案是真正使用延迟扩展。
""
第四个解决方案是使用延迟扩展的紧凑版本,类似于 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 (
set "Element=!ListOFElts[%%I]!"
%SystemRoot%\System32\whoami.exe /groups /fo list | %SystemRoot%\System32\find.exe "!Element!"
)
命令 FINDSTR 可以指定多个搜索字符串。
@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"
指定的三个字面和区分大小写的解释字符串中的任何一个。批处理文件中的这一个命令行将替换上面的所有四个批处理文件。
要了解使用的命令及其工作原理,请打开命令提示符窗口,执行以下命令,并完全阅读为每个命令显示的所有帮助页面。
/C:"..."
call /?
echo /?
endlocal /?
find /?
findstr /?
for /?
set /?
setlocal /?
另请参阅Why is no string output with 'echo %var%' after using 'set var = text' on command line?上的答案,详细说明为什么在上面的批处理文件中使用所有 SET 命令行whoami /?
而不仅仅是"variable=value"
。
答案 2 :(得分:0)
除非出于学习/隐藏目的,否则 为什么不简单地使用
for %%A in (First Second Third) Do whoami /groups /fo list | find "%%A"
甚至
whoami /groups /fo list | findstr "First Second Third"