我想初始化一个矩阵,然后在几个地方迭代它。
到目前为止,这是基于我从其他问题中可以找到的内容,但显然我正在做一些可怕的错误,因为在回声中服务是空的。
代码
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初始化有什么问题,一旦设置,如何迭代该矩阵将值传递给其他调用?
之前可能已经回答了这个问题,但我认为其他答案假设的知识水平高于我的水平,那么您能否以一种不需要工作批处理文件知识的方式进行解释?此外,支持空间很重要。
答案 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 - 被指定为%%a
,2
是第一个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
到
(请注意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
。考虑如果调用例程将会发生什么不止一次 - 如果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