如何使用数组元素作为循环中另一个数组的索引?

时间:2018-11-24 12:52:15

标签: arrays indexing cmd

我有一个小问题,无法动动脑筋。这是代码:

SET onts=3

SET port[1]=0
SET port[2]=3
SET port[3]=2

SET free[0]=8
SET free[1]=5
SET free[2]=5
SET free[3]=15

FOR /L %%A IN (1,1,%onts%) DO (
    SET /A ont[%%A]=%free[%port[%%A]%]%
)

echo %ont[1]%
echo %ont[2]%
echo %ont[3]%

我希望代码将变量0的第一次循环迭代值port[1]作为索引,因此访问变量free[0]将其值8分配给变量{{1 }}。在第二次迭代中,应使用变量ont[1]的值3来获取分配给变量port[2]的变量15的值free[3]。并且在第三次迭代中,在从ont[2]读取值ont[3]之后,应使用5的值free[2]定义变量2

因此输出应为:

port[3]

但是批处理文件输出:

8
15
5

我尝试在循环中使用第二个变量:

0
3
2

但是它也不起作用。

我也尝试过调用一个函数来将此代码外包,但是仍然没有结果-我不确定,我可能做错了什么。

有人对如何使其工作有任何想法吗?

2 个答案:

答案 0 :(得分:2)

我建议先阅读How does the Windows Command Interpreter (CMD.EXE) parse scripts?

Windows命令处理器解析从(开始并以匹配的)结尾的整个命令块,并分别用环境变量的当前值替换由%variable%完成的环境变量的所有值引用环境变量不存在。

对于命令行SET /A ont[%%A]=%free[%port[%%A]%]%,这意味着cmd.exe%free[%解释为名为free[的环境变量的值引用,并将%]%解释为名为环境变量的值引用],然后执行命令 FOR 。在 FOR 命令行上方没有定义环境变量free[],并且可以预期在启动批处理文件之前根本不存在这样的环境变量。因此,Windows命令处理器在预处理阶段之后最终将执行以下命令行:

FOR /L %A IN (1 1 3) DO (SET /A ont[%A]=port[%A] )

在运行批处理文件时,可以完全按照命令提示符窗口中的说明(通常不使用@echo off作为第一个命令行来运行)。

一种解决方案是使用delayed expansion和另一个 FOR 循环来获取free[y]的值,具体取决于分配给环境变量{{1 }}。

port[x]

此批处理文件的输出为:

ont[x]

要了解所使用的命令及其工作方式,请打开命令提示符窗口,在其中执行以下命令,并非常仔细地阅读每个命令显示的所有帮助页面。

  • @echo off setlocal EnableExtensions EnableDelayedExpansion set "onts=3" set "port[1]=0" set "port[2]=3" set "port[3]=2" set "free[0]=8" set "free[1]=5" set "free[2]=5" set "free[3]=15" for /L %%A IN (1,1,%onts%) do for %%B in (!port[%%A]!) do set "ont[%%A]=!free[%%B]!" echo %ont[1]% echo %ont[2]% echo %ont[3]% endlocal
  • 8 15 5
  • echo /?
  • endlocal /?
  • for /?

最后,我建议阅读Why is no string output with 'echo %var%' after using 'set var = text' on command line?上的答案

答案 1 :(得分:1)

您的方法需要两个(实际上是代码块)三个延迟扩展级别,而您没有使用。

我的previous answer演示了如何使用delayed expansion

Mofi的好answer显示了一种使用for克服双重延迟扩展的方法,
这是另一个带有伪调用的代码:

:: Q:\Test\2018\11\24\SO_53458343.cmd
@Echo off&SetLocal EnableExtensions EnableDelayedExpansion
SET onts=3

SET port[1]=0
SET port[2]=3
SET port[3]=2

SET free[0]=8
SET free[1]=5
SET free[2]=5
SET free[3]=15

FOR /L %%A IN (1,1,%onts%) DO Call SET /A "ont[%%A]=%%free[!port[%%A]!]%%"

echo ont[1]=%ont[1]%
echo ont[2]=%ont[2]%
echo ont[3]=%ont[3]%

> Q:\Test\2018\11\24\SO_53458343.cmd
ont[1]=8
ont[2]=15
ont[3]=5