batch-filetoken

How to use variables (their values) as tokens with the for command - Win BATCH file


So the situation is like so... I have two nested if statements and then a loop inside them (using the GoTo command and an incremented variable - for loop simulation :D). As you probably know to assign new values to variables inside of parentheses (of an if statement) you have to use delayedexpansion. Also to use variables in the for command you have to double the percent marks like so %%. I want to set the tokens in a for /f command to be the value of the variables I'd like. The problem is doubling the exclamation marks has no effect. I also tried all sorts ... like using quotes, escaping those quotes, using quote alternatives, but it was all to no avail. If you can help in any way that would be just great, because I can't think of anything at all :(. Thank you in advance guys!

If that made no sense here's the code:

@echo off
set FilePath=test.bat
set RefreshRate=3
setlocal enabledelayedexpansion enableextensions
:GetData
if defined FilePath (
if exist "%FilePath%" (
:GetLines
cls
:: This is how I find out how many lines there is in the file
set "cmd=findstr /R /N "^^" "%FilePath%" | find /C ":""
for /f %%a in ('!cmd!') do set Lines=%%a
:ShowCode
cls
set LineNum+=1
if ""!LineNum!"" GTR ""!Lines!"" GoTo Refresh

::THIS IS THE MAIN PROBLEM
for /f "tokens=%%LineNum%% delims=$" %%b in ("%FilePath%") do (

set Line%LineNum%=%%b
echo !LineNum!. | !Line%LineNum%!
GoTo ShowCode
)
)
)
:Refresh
ping localhost -n %RefreshRate% >nul
GoTo GetData

I'm sorry that I didn't have enough time to make it more readable, but it should make the whole thing a little clearer.


Solution

  • First: use neither :: remark comments nor :label in a code block enclosed in () parentheses. A proof of harmfulness you could find in the labels.bat script encoded in output from a script provided thereinafter; an explanation here: Comments within bracketed code blocks.

    In next script, non-empty lines of a particular plain text file (cf. set "FilePath=labels.bat") are saved to a pseudo-array LineAAA, where index AAA = line number. I do not know whether it isn't off topic according to your question but could give some useful clue...

    @echo off
    setlocal enabledelayedexpansion enableextensions
    cls
    set line
    set "FilePath=labels.bat"
    set /A "RefreshRate=3"
    :GetData
    if not defined FilePath (
      echo %%FilePath%% not defined
      goto :eof
    )
    if not exist "%FilePath%" (
      echo %FilePath% does not exist
      goto :eof
      rem  following 'else' (sub)statement seems to be superabundant 
    ) else (
        rem GetLines
        rem This is how I find out how many lines there is in the file
        set "cmd=findstr /R /N "^^" "%FilePath%" | find /C ":""
        for /f %%a in ('!cmd!') do set /A "Lines=%%a"
        set /A "LineNum=0"
        set "Line000=@rem %FilePath%"
        for /f "tokens=*" %%b in (%FilePath%) do (
          set /A "LineNum+=1"
          set "LineX=000000000!LineNum!"  
          set "LineX=!LineX:~-3!"  
          set "Line!LineX!=%%b"
        )
        call :Refresh
    )
    set line
    rem pause
    endlocal
    goto :eof
    
    :Refresh
      ping localhost -n %RefreshRate% | findstr /I "Packets: statistics"
      rem >nul
    GoTo :eof
    

    Output:

    Environment variable line not defined
    Ping statistics for ::1:
        Packets: Sent = 3, Received = 3, Lost = 0 (0% loss),
    Line000=@rem labels.bat
    Line001=@SETLOCAL enableextensions enabledelayedexpansion
    Line002=@ECHO ON >NUL
    Line003=if ""=="" (
    Line004=rem comment
    Line005=@echo rem comment
    Line006=)
    Line007=if ""=="" (
    Line008=:: comment
    Line009=@echo :: comment
    Line010=)
    Line011=if ""=="" (
    Line012=:label
    Line013=@echo :label
    Line014=)
    Line015=@ENDLOCAL
    Line016=@goto :eof
    LineNum=16
    Lines=16
    LineX=016
    

    labels.bat output:

    d:\bat>labels.bat
    
    d:\bat>if "" == "" (
    rem comment
    
    )
    rem comment
    
    d:\bat>if "" == "" (@echo :: comment )
    '@echo' is not recognized as an internal or external command,
    operable program or batch file.
    
    d:\bat>if "" == "" (@echo :label )
    '@echo' is not recognized as an internal or external command,
    operable program or batch file.
    
    d:\bat>