1

在批处理文件中引用迭代数组

我有以下内容:

for /f "tokens=1" %%Q in ('query termserver') do (
    if not ERRORLEVEL (
        echo Checking %%Q
        for /f "tokens=1" %%U in ('query user %UserID% /server:%%Q') do (echo %%Q)
    )
)

query termserver从命令行运行时,前两行是:

Known
------------------------- 

...后面是终端服务器列表。但是,我不想将这些作为query user命令的一部分。此外,我不想包括大约 4 台服务器。当我提供UserID此代码时,程序会立即退出。我知道这与if声明有关。这不可能在for循环中嵌套流控制吗?

我曾尝试将变量设置为我想要检查的服务器的名称,但迭代将在第一台服务器上结束:

set TermServers=Server1.Server2.Server3.Server7.Server8.Server10

for /f "tokens=2 delims=.=" %%Q in ('set TermServers') do (
    echo Checking %%Q
    for /f "tokens=1" %%U in ('query user %UserID% /server:%%Q') do (echo %%Q)
)

如果没有别的清洁,我更喜欢第二个例子而不是第一个例子。

任何有关这些问题的帮助将不胜感激。

4

2 回答 2

3

同样,这里有很多事情需要注意。

if errorlevel

的帮助if说:

IF [NOT] ERRORLEVEL number command

作为if errorlevel条件的语法。也就是说,您必须提供一个数字进行比较。请记住,如果退出代码至少为n ,则if errorlevel n计算结果为true 。

所以

if errorlevel 1 ...

捕获任何错误(通过退出代码发出信号),而

if errorlevel 0 ...

简单地说总是正确的。

无论如何,你可能想要一个

if not errorlevel 1 ...

在这里,因为如果没有发生错误,则该条件为真。

跳线

for /f命令有一个参数skip=n,可用于在开始时跳过行。如果您的输出以您不想要的两行开头,那么您可以这样做

for /f "skip=2 tokens=1" %%Q in ('query termserver') do

迭代多个已知值for /f

您的第二个代码片段的问题是for迭代line-wise。所以当你给它一个单一的环境变量时,它会对其进行标记(并将标记放入不同的变量中),但循环每行只运行一次。另请注意,set在这里使用有点容易出错,因为您可能会得到比您想要的更多的回报。就像是

for /f ... in ("%TermServers%") ...

本来会更容易。尽管如此,这并不能解决最初的问题。解决此问题的最简单方法可能如下所示:

rem space-separated list of servers
set TermServers=Server1 Server2 Server3 Server7 Server8 Server10

rem call the subroutine with the list of servers
call :query_servers %TermServers%

rem exit the batch file here, to prevent the subroutine from running again afterwards
goto :eof

rem Subroutine to iterate over the list of servers
:query_servers

  rem Process the next server in the list
  rem Note the usage of %1 here instead of a for loop variable
  echo Checking %1          
  for /f "tokens=1" %%U in ('query user %UserID% /server:%1') do (echo %%Q)

  rem Remove the first argument we just processed
  shift

  rem if there is still another server to be processed, then do so
  rem we're mis-using the subroutine label as a jump target here too
  if not [%1]==[] goto query_servers

rem This is kind of a "return" statement for subroutines
goto :eof

(未经测试,但应该可以工作。)

ETA:哎呀,我又一次错过了最明显的答案:

set TermServers=Server1 Server2 Server3 Server7 Server8 Server10
for %%S in (%TermServers%) do (
    for /f "tokens=1" %%U in ('query user %UserID% /server:%1') do (echo %%Q)
)

请注意,这很简单for不是 for /f,它将尽职尽责地遍历值列表。我不知道我是怎么错过的,对不起。

于 2010-04-29T22:42:13.027 回答
-2

NT shell/batch 语言不够聪明,无法接受IF NOT ERRORLEVEL (...——您需要进行显式比较,如下所示:

if not %ERRORLEVEL%==0 (
...
于 2010-04-28T19:29:04.250 回答