数组索引窗口批处理上的双重扩展



在 for 循环中,我试图访问CLs中索引count处的元素(这行代码:echo !!CLs[!count!]!!(,但我不确定如何做到这一点。我真的不明白在这种情况下扩展是如何工作的,所以你在下面看到的是我突然尝试的东西。

@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

谢谢

根据帖子 Windows 命令解释器 (CMD.EXE( 如何解析脚本?(请参阅阶段 5(,行echo !!CLs[!count!]!!不起作用,因为开头!!折叠为单个!,然后!CLs[!扩展到空字符串(假设未定义此类变量(,然后按字面返回count,然后将!]!扩展为空字符串,并忽略最后的!。换句话说,延迟扩展不能嵌套。

您可以使用call来引入另一个解析阶段,如下所示:

call echo %%CLs[!count!]%%

IF NOT %%I == CLs[!count!] ( ... )错误,您也必须扩展正确的值。但是,不幸的是,call if无济于事,因为if(如forrem(是一个特殊的命令,比其他命令更早被解析器识别,例如call

要解决此问题,您可以将!count!的值存储在for元变量中,例如%%J,引入另一个解析阶段,然后使用!CLs[%%J]!,如下所示:

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"
)
)
)

另一种更慢的可能性是将相关代码放入子例程中:

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

你也可以看看 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

我使用了一个名为q58209698.txt的文件,其中包含一些虚拟数据进行测试,并选择使用整个数据线,没有合适的文件存在token 5

请注意,作为奖励,我添加了clscnt- 一个发生计数数组。

所示:实现查找/计数唯一令牌目标的两种不同方法。当然,如果cls数组预先加载了所需的令牌,那么调整代码以检测/报告这些令牌的出现是基本的程序员。

这两种方法相似。首先,set用于列出从cls[开始的已建立变量。第一个if确保只处理数组名cls,然后要么是重复(prcoessed设置为一个值并增加出现计数器(,要么是新值(当for...%%a循环结束时,processed仍然未定义(,所以记录它。

第二种方法更直接,使用count的值专门询问cls数组中的值。

最新更新