[英]Double Expansion on Array Index Windows Batch
Inside the for loop I'm trying to access the element at index count
in CLs
(this line of code: echo !!CLs[!count!]!!
), but I'm not sure how to do this.在 for 循环中,我试图访问
CLs
中索引count
处的元素(这行代码: echo !!CLs[!count!]!!
),但我不知道该怎么做。 I don't really understand how expansion works in this case, so what you see below it me trying something out of no where.我真的不明白在这种情况下扩展是如何工作的,所以你在下面看到的我在不知从哪里尝试一些东西。
@ECHO off
setlocal enableextensions enabledelayedexpansion
SET CLs[0]=#
SET /A count = 0
FOR /F "tokens=5" %%I IN ('some command') DO (
echo !!CLs[!count!]!! :: THIS LINE
IF NOT %%I == CLs[!count!] (
SET /A count += 1
SET CLs[!count!]=%%I
)
)
echo The item is %CLs[10]%
endlocal
Thanks谢谢
According to the post How does the Windows Command Interpreter (CMD.EXE) parse scripts?根据帖子Windows 命令解释器(CMD.EXE)如何解析脚本? (see phase 5), the line
echo !!CLs[!count!]!!
(参见第 5 阶段),行
echo !!CLs[!count!]!!
cannot work, because the opening !!
不能工作,因为开幕
!!
are collapsed to a single !
都塌成一个
!
, then !CLs[!
, 然后
!CLs[!
is expanded to an empty string (assuming such variable is not defined), then count
is returned literally, then !]!
扩展为空字符串(假设未定义此类变量),然后按字面意思返回
count
,然后!]!
is expanded to an empty string and the final !
扩展为一个空字符串和最后一个
!
is dismissed.被解雇。 Or in other words, delayed expansion cannot be nested.
或者换句话说,延迟扩展不能嵌套。
You can use call
though to introduce another parsing phase, like this:您可以使用
call
来引入另一个解析阶段,如下所示:
call echo %%CLs[!count!]%%
The line IF NOT %%I == CLs[.count.] (... )
is wrong, you must expand the right value too. IF NOT %%I == CLs[.count.] (... )
行是错误的,您也必须扩展正确的值。 However, call if
will not help unfortunately, because if
(like for
and rem
) is a special command that is recognised by the parser earlier than others, like call
.然而,不幸的是,
call if
并没有帮助,因为if
(如for
和rem
)是一个特殊的命令,解析器比其他命令更早地识别它,如call
。
To work around that you can store the value of !count!
要解决这个问题,您可以存储
!count!
in a for
meta-variable, like %%J
, for instance, to introduce another parsing phase, and use !CLs[%%J]!
在
for
元变量中,例如%%J
,以引入另一个解析阶段,并使用!CLs[%%J]!
then, like this:然后,像这样:
set /A "count=0"
for /F "tokens=5" %%I in ('some command') do (
for %%J in (!count!) do (
echo !CLs[%%J]!
if not "%%I" == "!CLs[%%J]!" (
set /A "count+=1"
set "CLs[!count!]=%%I"
)
)
)
Another yet slower possibility is to put the relevant code into a sub-routine:另一种较慢的可能性是将相关代码放入子例程中:
set /A "count=0"
for /F "tokens=5" %%I in ('some command') do (
call :SUB !count!
)
goto :EOF
:SUB
echo !CLs[%~1]!
if not "%%I" == "!CLs[%~1]!" (
set /A "count+=1"
set "CLs[%~1]=%%I"
)
goto :EOF
You may also take a look at the post Arrays, linked lists and other data structures in cmd.exe (batch) script about how to deal with such pseudo-arrays.您还可以查看 Arrays 中的帖子cmd.exe(批处理)脚本中的链表和其他数据结构,了解如何处理此类伪数组。
ECHO ------------- START AT %time%
REM <!-- language: lang-dos -->
@ECHO Off
setlocal enableextensions ENABLEDELAYEDEXPANSION
SET "sourcedir=U:\sourcedir"
SET "filename1=%sourcedir%\q58209698.txt"
SET CLs[0]=#
SET /a clscnt[0]=0
SET /A count = 0
FOR /F "tokens=*" %%I IN ('type %filename1%') DO (
SET "processed="
FOR /f "tokens=1,2,3delims=[]=" %%a IN ('set cls[') DO IF /i "%%a"=="cls" (
IF "%%I"=="%%c" (SET /a clscnt[%%b]+=1&SET "processed=y")
)
IF not DEFINED processed SET /a count+=1&SET "cls[!count!]=%%I"&SET /a clscnt[!count!]=1
)
FOR /L %%a IN (0,1,%count%) DO ECHO !clscnt[%%a]! times !cls[%%a]!
ENDLOCAL
ECHO -------------------------Second way -----------------
@ECHO Off
setlocal enableextensions ENABLEDELAYEDEXPANSION
SET "sourcedir=U:\sourcedir"
SET "filename1=%sourcedir%\q58209698.txt"
SET CLs[0]=#
SET /a clscnt[0]=0
SET /A count = 0
FOR /F "tokens=*" %%I IN ('type %filename1%') DO (
SET "processed="
FOR /L %%a IN (0,1,!count!) DO (
IF "%%I"=="!cls[%%a]!" (SET /a clscnt[%%a]+=1&SET "processed=y")
)
IF not DEFINED processed SET /a count+=1&SET "cls[!count!]=%%I"&SET /a clscnt[!count!]=1
)
FOR /L %%a IN (0,1,%count%) DO ECHO !clscnt[%%a]! times !cls[%%a]!
ENDLOCAL
GOTO :EOF
I used a file named q58209698.txt
containing some dummy data for my testing and chose to use the entire data line, having no suitable files where token 5
existed.我使用了一个名为
q58209698.txt
的文件,其中包含一些用于我的测试的虚拟数据,并选择使用整个数据行,没有合适的文件存在token 5
。
Note that as a bonus, I've added clscnt
- an array of occurence-counts.请注意,作为奖励,我添加了
clscnt
- 出现计数的数组。
Shown: two separate ways of achieving the aim of finding/counting the unique tokens.显示:实现查找/计算唯一令牌目标的两种不同方法。 Naturally, if the
cls
array is pre-loaded with the required tokens, then it's basic-programmer's-play to adjust the code to detect/report occurrences of those tokens.自然地,如果
cls
数组预先加载了所需的令牌,那么基本程序员的工作就是调整代码以检测/报告这些令牌的出现。
The two methods are similar.这两种方法是相似的。 In the first,
set
is used to list the established variables starting cls[
.首先,
set
用于列出以cls[
开头的已建立变量。 The first if
ensures processing only the array-name cls
, then either it's a repeat (set prcoessed
to a value and increment the occurrences-counter) or it's a new value (when the for...%%a
loop ends, processed
is still undefined) so record it.第一个
if
确保仅处理数组名称cls
,然后它是重复的( prcoessed
为一个值并增加出现计数器)或者它是一个新值(当for...%%a
循环结束时, processed
的是仍然未定义)所以记录它。
The second way is more direct, using the value of count
to specifically interrogate the values in the cls
array.第二种方式更直接,使用
count
的值专门查询cls
数组中的值。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.