Variables BAT文件:作为另一个变量的一部分的变量内容

Variables BAT文件:作为另一个变量的一部分的变量内容,variables,batch-file,Variables,Batch File,假设我有一个变量a,内容为“123”和一个变量b123,其中包含一些文本。出于某种原因,我想使用变量a作为第二个变量名的一部分。大概是这样的: SET a=123 SET b123=some_text_in_it rem i want next line to output "some_text_in_it" echo %b%a%% 所以我想将文本与var内容连接起来,并使用结果字符串作为变量名来回显该内容。上面的示例不起作用,我明白了原因,可能我需要添加一些分组。如何做到这一点,最好是一行

假设我有一个变量a,内容为“123”和一个变量b123,其中包含一些文本。出于某种原因,我想使用变量a作为第二个变量名的一部分。大概是这样的:

SET a=123
SET b123=some_text_in_it
rem i want next line to output  "some_text_in_it"
echo %b%a%%

所以我想将文本与var内容连接起来,并使用结果字符串作为变量名来回显该内容。上面的示例不起作用,我明白了原因,可能我需要添加一些分组。如何做到这一点,最好是一行?

有两种常见的方法
呼叫
延迟扩展

setlocal EnableDelayedExpansion
SET a=123
SET b123=some_text_in_it
rem i want next line to output  "some_text_in_it"
call echo %%b%a%%%
echo !b%a%!
调用
变量使用这样一个事实,即调用将第二次重新分析线路,第一次仅扩展
%a%
,而双
%
将减少为单个
%

呼叫回显%b123%

在第二步中,将展开
%b123%

但是,
调用
技术速度慢且不太安全,因此应首选延迟扩展

DelayedExpansion的工作原理是,感叹号在比百分比展开更晚的解析器阶段展开。
这也是为什么延迟扩张更安全的原因

编辑:包含数字的数组的方法 如果您使用的阵列只包含数字,您也可以使用
set/a
访问它们。
这比
FOR
CALL
技术简单得多,而且它也可以在块中工作

setlocal EnableDelayedExpansion
set arr[1]=17
set arr[2]=35
set arr[3]=77
(
  set idx=2
  set /a val=arr[!idx!]
  echo !var!
)
“使用变量作为第二个变量名的一部分”的最佳理由是通过下标变量访问数组(向量和矩阵)元素。虽然这与上面的示例完全相同,但看起来更清楚:

setlocal EnableDelayedExpansion
set i=123
set v[123]=Value of element 123
call echo %%v[%i%]%%
echo !v[%i%]!
尽管
调用
延迟扩展
慢,正如jeb上面所说的,它可以嵌套多次,允许使用第二个(或更深的)间接寻址来访问数组元素。此功能可用于复杂的数据结构,如链表。例如:

set i=123
set v[123]=456
set w[456]=Value of element 456
call call echo %%%%w[%%v[%i%]%%]%%%%
编辑:由于某种原因,我不明白,上一个命令的延迟扩展版本无法正常工作:

call echo !w[%%v[%i%]%%]!

如果两个变量都被分配到展开它们的同一个括号块中,那么还有一种方法非常有用。该解决方案类似于jeb的延迟展开回答,只是它使用了一个FOR变量,而不是正常展开

@echo off
setlocal enableDelayedExpansion

:: Define a linefeed value - only needed for last variant
set LF=^


:: The two blank lines above are critical to the definition of LF

(
  set A=123
  set B123=some_text_in_it

  rem ECHO !B%A%! will fail because A was assigned within the same block

  rem This works as long as A does not contain * or ?
  for %%A in ("!A!") do echo !B%%~A!

  rem This works as long as A does not start with EOL character (; by default)
  for /f "delims=" %%A in ("!A!") do echo !B%%A!

  rem This will never fail because it disables EOL by setting it to a linefeed
  for /f eol^=^%LF%%LF%^ delims^= %%A in ("!A!") do echo !B%%A!
)
也可以使用呼叫技巧,但相对而言,它非常慢,而且不可靠-请参阅

有关linefeed变量的定义和使用,请参见

有关将EOL设置为换行的详细信息,请参见。使用LF变量而不是在FOR语句中嵌入换行符只是该技术的扩展。它使代码更具可读性

编辑
安全地将FOR技术用于任何有效值的更简单方法是将EOL设置为等号,因为用户定义的变量名称中不能包含=

for /f "eol== delims=" %%A in ("!A!") do echo !B%%A!

呼叫echo!w[%%v[%i%]%%]将按标准顺序展开。1.呼叫回声的扩展百分比
!w[%v[123]]%,2。延迟扩展到
调用echo
,因为
w[%v[123]]]
不是定义的变量,3。调用将被执行并开始新的百分比扩展。您的示例应该看起来像
call echo%%w[!v[%i%]!]%%
Btw。在呼叫后,延迟的扩展将永远不会执行,在@Aacini中解释:嗯,我使用此功能也有类似的原因。在几种语言中,有许多字符串以常量形式本地化,除了后缀外,其他名称都相同(例如,“my_text_1_de”,“my_text_1_it”…)。所以我的目标是在用户选择语言后,为变量分配适当的i18n字符串。@jeb:当然!:延迟扩展是在执行命令之前完成的,在这种情况下(
call
),它负责百分号的第二次扩展。非常感谢:)@AleksandrKravets:我建议您将变量名的更改部分用括号括起来,就像其他语言中的标准数组一样?”my_text_1[de],“my_text_1[it]”虽然这对于批处理是相同的,但对于程序员来说更清晰@Aacini:也请原谅,但您提出的解决方案是一种变通方法,而不是您可以在Python、Perl或任何普通编程语言中找到的数组支持。您甚至可以将其视为哈希表(记住,索引是字符串)。但它不是一个真正的哈希表,它是Q&D解决方案,有用、直观,但仍然是一个解决方案。也许我在吹毛求疵,但这是因为我不是一个真正的蝙蝠爱好者,我只需要使用蝙蝠文件。@jeb:虽然
set/a
对访问数字数组元素很有用,但它不能使用在同一
set/a
命令中修改的索引,原因与您在下面解释的相同。例如:
set/a idx+=1,var=arr[!idx!]
没有获得正确的元素,因此必须通过两个独立的
set/a
命令来实现此管理。