如何设置和迭代矩阵

时间:2017-06-12 18:37:12

标签: windows loops batch-file matrix

我想初始化一个矩阵,然后在几个地方迭代它。

到目前为止,这是基于我从其他问题中可以找到的内容,但显然我正在做一些可怕的错误,因为在回声中服务是空的。

代码

rem SET SERVICES[#][0]="Window Title"
rem SET SERVICES[#][1]="Relative .bat path"

SET SERVICES[0][0]="Hello World!"
SET SERVICES[0][1]="service/hello.bat"
SET SERVICES[1][0]="Hello World! 2"
SET SERVICES[1][1]="service/hello 2.bat"

for %%s in (%SERVICES%) do call ServiceStarter.bat %%s[0] %%s[1]

for %%s in (%SERVICES%) do call ServiceStopper.bat %%s[0]

输出

C:\securboration>SET SERVICES[0][0]="Hello World!"

C:\securboration>SET SERVICES[0][1]="service/hello.bat"

C:\securboration>SET SERVICES[1][0]="Hello World! 2"

C:\securboration>SET SERVICES[1][1]="service/hello 2.bat"

C:\securboration>for %s in ((null)) do call ServiceStarter.bat %s[0] %s[1]

C:\securboration>for %s in ((null)) do call ServiceStopper.bat %s[0]

预期

它应该循环通过外部数组,以便我可以将子数组的元素作为参数传递给其他.bat文件。

所以 Matrix初始化有什么问题,一旦设置,如何迭代该矩阵将值传递给其他调用?

之前可能已经回答了这个问题,但我认为其他答案假设的知识水平高于我的水平,那么您能否以一种不需要工作批处理文件知识的方式进行解释?此外,支持空间很重要。

2 个答案:

答案 0 :(得分:1)

<!-- language: lang-dos -->

@ECHO OFF
SETLOCAL
rem SET SERVICES[#][0]="Window Title"
rem SET SERVICES[#][1]="Relative .bat path"

SET SERVICES[0][0]="Hello World!"
SET SERVICES[0][1]="service/hello.bat"
SET SERVICES[1][0]="Hello World! 2"
SET SERVICES[1][1]="service/hello 2.bat"

for /f "tokens=2,3*delims=[]=" %%a in ('set SERVICES[') do IF %%b==0 CALL call q44506472_s.bat %%services[%%a][0]%% %%services[%%a][1]%%
for /f "tokens=2,3*delims=[]=" %%a in ('set SERVICES[') do IF %%b==0 CALL call q44506472_s.bat %%c %%services[%%a][1]%%


GOTO :EOF

其中q44506472_s.bat是包含

的虚拟演示文件
@ECHO OFF
SETLOCAL
ECHO parameter1=%1
ECHO parameter2=%2
ECHO ----------------

(仅显示正在传输的参数)

所以 - 象形文字这样做:

执行set services[命令,该命令以services[格式列出以services[0][1]=somestring开头的所有变量。

for /f标记set生成的每一行,使用三个字符[]=作为分隔符。因此,使用services[0][1]=somestring,我们得到

services作为token1 - 未分配的 0作为令牌2 - 被指定为%%a2是第一个token号码被提名的 1作为令牌3 - 被指定为%%b 3是指定的下一个token号码 somestring作为令牌*(最高提名令牌后的余数) - 已分配给%%c

令牌由任何所选分隔符的任何序列分隔。

因此,选择%%b == 0将选择第二个数组维度= 0,然后我们通过call执行call,例如%%services[%%a][0]%%已解决as 服务[0] [0] 的内容。由于此时%%a是一个活动的元变量,它首先被替换,然后解析器将剩余的%%解析为%%转义%)。< / p>

第一个call执行解析派对技巧;第二个执行实际子程序并解析参数。

由于%%c无偿地包含第一个参数所需的内容,如果您愿意,也可以使用它。

你从那里开发 - 好吧,cmd并不是最聪明的 - 我觉得你有点太聪明了。有两个问题 - 第一个是引用windowtitle...,造成破坏,第二个是你“引用字符串”作为变量值。就个人而言,我根据需要应用引号,并使用cmd特征语法SET "var=value"(其中value可能为空),用于确保任何杂散尾随空格不包含在赋值中。< / p>

我要改变

 for /f "tokens=2,3*delims=[]=" %%a in ('set SERVICES[') do IF %%b==0 CALL for /f "Delims=:" %%A in ('tasklist /v /fi "WINDOWTITLE eq %%services[%%a][0]%%"') do if %%A==INFO SET errorinfo=1

(请注意cmdfor/f命令中单引号之前/之后的换行非常满意 - 只是让线条更容易编辑...)

for /f "tokens=2,3*delims=[]=" %%a in ('set SERVICES['
 ) do IF %%b==0 CALL :seterrorinfo %%services[%%a][0]%%

ECHO errorinfo="%errorinfo%"

GOTO :EOF

:seterrorinfo
for /f "Delims=:" %%A in ('tasklist /v /fi "WINDOWTITLE eq %~1"') do ECHO ***%%A***&if %%A==INFO SET errorinfo=1

GOTO :eof

:seterrorinfo现在是一个子程序,提供了数组中的引用值作为参数。

在子例程中,%~1被第一个参数的值替换,~运算符删除任何封闭的引号。

我不会评论INFO的检测是否合适(但我建议在例程开始时清除errorinfo。考虑如果调用例程将会发生什么不止一次 - 如果errorinfo在下次通话时%%A不是INFO,则前一个通话的值将保留在echo %%A。)我已将delayed expansion留在子程序中便于分析。

请注意,如果您在SO上阅读了有关call set的一些文章,您可以使用它来避免! kludge。您的原始数据包含!,因此我将其作为NaN避免使用,然后成为特殊字符。

答案 1 :(得分:0)

这仍然可以使用最基本的for循环以更简单的方式完成。 关键在于迭代变量名的正确部分,以减少扩展该变量名所需的代码。

在这种情况下,可用的服务索引及其分隔符。

@echo off
    Set Services="0][0" "0][1" "1][0" "1][1"
    Set SERVICES[0][0]="Hello World!"
    Set SERVICES[0][1]="service/hello.bat"
    Set SERVICES[1][0]="Hello World! 2"
    Set SERVICES[1][1]="service/hello 2.bat"

For %%A in (%Services%) do (
    CALL echo(%%Services[%%~A]%%
    Choice /N /C NY /M "Start Service? NY"
    If Errorlevel 2 Call :service %%Services[%%~A]%%
)
    pause
    Exit /B
:service
    Echo( Service Selected: %1
    pause
Exit /B

此外,您可以将每个索引分配给要执行的特定命令:

@echo off
    Set Services="0][0" "0][1" "1][0" "1][1"
    Set "0][0=Echo(A command or Parameter for service 0 0"
    Set "0][1=Echo(A command or Parameter for service 0 1"
    Set "1][0=Echo(A command or Parameter for service 1 0"
    Set "1][1=Echo(A command or Parameter for service 1 1"
    SET SERVICES[0][0]="Hello World!"
    SET SERVICES[0][1]="service/hello.bat"
    SET SERVICES[1][0]="Hello World! 2"
    SET SERVICES[1][1]="service/hello 2.bat"

    Setlocal EnableDelayedExpansion
For %%A in (%Services%) do (
    echo(!Services[%%~A]!
    Choice /N /C NY /M "Start Service? NY"
    If Errorlevel 2 Call :service "!%%~A!" "!Services[%%~A]!"
)
pause
Exit /B
:service
%~1 !%~2!
pause
Exit /B