Variables BAT文件:作为另一个变量的一部分的变量内容
假设我有一个变量a,内容为“123”和一个变量b123,其中包含一些文本。出于某种原因,我想使用变量a作为第二个变量名的一部分。大概是这样的: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内容连接起来,并使用结果字符串作为变量名来回显该内容。上面的示例不起作用,我明白了原因,可能我需要添加一些分组。如何做到这一点,最好是一行
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
命令来实现此管理。