【问题标题】:Batch find command with variable带变量的批量查找命令
【发布时间】:2018-05-31 09:03:27
【问题描述】:

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

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"

感谢您的帮助。

【问题讨论】:

标签: windows batch-file for-loop find


【解决方案1】:

我的最佳猜测:

@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

【讨论】:

  • 我很抱歉,但是如果我有更多的 "ListOfElts[n]" 直到像 n=100 怎么办?我必须改变什么?我试图理解 FOR /F 命令的逻辑,但我不明白。谢谢...
  • @MickaëlADRAR,没关系,除了设置它们,代码保持不变。
  • 好的,谢谢!我只是对 In('Set ListOfElts[ 2^>Nul') 代码感到好奇:'2' 是什么意思?我认为我必须根据元素的数量调整该值。
  • 在这种情况下,^ 仅用作运行括号内内容的隐藏 cmd 上下文的转义字符。因此看到的是2>Nul,这是一个标准错误重定向到NUL 设备,(有效防止错误消息的输出)。这个想法是,如果命令 Set ListOfElts[ 不匹配任何现有变量,错误消息 (Environment variable ListOfElts[ not defined) 不会不必要地触发 Do 部分。
【解决方案2】:

首先,打开命令提示符窗口,运行set /? 并在几页上阅读命令SET 的完整帮助输出。它在 IFFOR 示例中解释了 delayed expansion 的用法。

阅读答案很可能也有帮助:
How does the Windows Command Interpreter (CMD.EXE) parse scripts?

您的批处理文件在顶部包含setlocal enabledelayedexpansion,以启用延迟的环境变量扩展。但是没有使用语法!VariableName! 引用环境变量来真正利用延迟的环境变量扩展。出于这个原因,"%Element%" 已被 Windows 命令处理器修改,它在解析以 ( 开头并以匹配 ) 结束的整个命令块到仅 "" 之前执行命令 FOR。环境变量 Element 在到达 FOR 命令行之前未定义,cmd.exe 解析整个 FOR 命令行,命令块以 ) 结尾执行FOR之前的批处理文件。

CALL 主要用于从一个批处理文件中调用一个子程序或另一个批处理文件。在简单的命令行上使用 CALL 可用于获取由 Windows 命令处理器解析两次的命令行,以避免使用延迟扩展。在前三个 SET 行中,绝对没有必要使用 CALL,因为第二次解析 SET 命令行时没有任何变化。 p>

第一个解决方案是不使用延迟扩展,使用 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 命令行强>第一次。所以在 FOR 执行之前,"%ListOFElts[%%I]%" 已经被替换为 ""

第三种解决方案是真正使用延迟扩展。

@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!"
)

第四个解决方案是使用延迟扩展的紧凑版本,类似于 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 /?

另请参阅Why is no string output with 'echo %var%' after using 'set var = text' on command line? 上的答案以详细解释为什么在所有 SET 命令行上使用"variable=value" 而不是在上面的批处理文件中仅使用variable=value

【讨论】:

    【解决方案3】:

    除非出于学习/隐藏目的,
    为什么不简单地使用

    for %%A in (First Second Third) Do whoami /groups /fo list | find "%%A"
    

    甚至

    whoami /groups /fo list | findstr "First Second Third"
    

    【讨论】:

      猜你喜欢
      • 2018-11-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-07-16
      • 1970-01-01
      • 1970-01-01
      • 2013-06-29
      相关资源
      最近更新 更多