0

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. 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

3
  • 1
    Have you tried Call Echo %%CLs[!count!]%%? Commented Oct 2, 2019 at 21:50
  • This would appear to be an X-Y problem <meta.stackexchange.com/questions/66377/what-is-the-xy-problem> Please post the actual problem you are attempting to solve. Are you attempting to find %%I in an established array of CLs (not the best name in batch since cls is a keyword) or add unique enties to the array CLs or what? Commented Oct 3, 2019 at 1:15
  • @Magoo I'm trying to make an array of just specific unique tokens from the command output. Does that help? Commented Oct 3, 2019 at 15:07

2 Answers 2

2

According to the post How does the Windows Command Interpreter (CMD.EXE) parse scripts? (see phase 5), the line echo !!CLs[!count!]!! cannot work, because the opening !! are collapsed to a single !, then !CLs[! is expanded to an empty string (assuming such variable is not defined), then count is returned literally, then !]! 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 echo %%CLs[!count!]%%

The line IF NOT %%I == CLs[!count!] ( ... ) is wrong, you must expand the right value too. 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.

To work around that you can store the value of !count! in a for meta-variable, like %%J, for instance, to introduce another parsing phase, and use !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.

Sign up to request clarification or add additional context in comments.

Comments

0
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.

Note that as a bonus, I've added clscnt - an array of occurence-counts.

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.

The two methods are similar. In the first, set is used to list the established variables starting 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.

The second way is more direct, using the value of count to specifically interrogate the values in the cls array.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.