批量查找带变量的命令

时间:2018-05-31 09:03:27

标签: windows batch-file for-loop find

我有一个字符串元素列表。

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"

感谢您的协助。

3 个答案:

答案 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"