<!-- 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 作为令牌1 - 未分配
0 作为令牌2 - 分配给%%a 作为2 是第一个token 号码指定
1 作为令牌3 - 分配给%%b因为3 是下一个token 提名号码
somestring 作为令牌*(最高提名令牌之后的剩余部分)-分配给%%c
标记由任何选定分隔符的任何序列分隔。
所以,选择%%b==0 将选择第二个数组维度 = 0,然后我们通过calling 执行call,例如%%services[%%a][0]%%,它被解析为服务的内容[0][0]。由于此时%%a 是一个活动元变量,它首先被替换,然后解析器将剩余的%% 解析为%(% 转义%)。
第一个 call 执行解析派对技巧;第二个执行实际的子程序并解析参数。
由于%%c 无偿包含第一个参数所需的内容,如果您愿意,也可以使用它。
从那里你的发展 - 好吧,cmd 并不是最聪明的 - 我认为你有点太聪明了。有两个问题 - 第一个是 windowtitle... 被引用,造成严重破坏,第二个是您将“引用字符串”作为变量值。就个人而言,我会根据需要应用引号,并使用 cmd 特征语法 SET "var=value"(其中值可能为空),用于确保分配的值中不包含任何杂散的尾随空格。
我会改变
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
到
(请注意,cmd 对直接在 for/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。考虑如果多次调用例程会发生什么 -如果%%A 在下一次调用中不是INFO,则上一次调用的值将保留在errorinfo 中。)为了便于分析,我将echo %%A 留在了子例程中。
请注意,如果您在 SO 上阅读了一些关于 delayed expansion 的文章,您也许可以使用它来避免 call set 混乱。您的原始数据包含!,所以我避免使用它,因为! 然后变成了一个特殊字符。