Batch variable inside a variable not working when called

两盒软妹~` 提交于 2020-01-16 01:17:38

问题


Inside Test.txt reads a URL on the first line, theres more but for this it unimportant.

setlocal EnableDelayedExpansion
set browser=chrome.exe
set i=0
for %%f in (Test.txt) do (
    set i=0
    for /F "delims=" %%l in (%%f) do (
        set /A i+=1
        set line!i!=%%l
        ))
::the above read the contents of Test.txt and saved each line to a different Variable made up of two variables
set x=0
:ReadLines
if %x% gtr %i% (
    goto Completed)
set /a x+=1
set /a odd=%x%%%2
if %odd%==1 (
    set Address=!line%x%!
    echo !Line%x%!
    ::the above echo's back the URL from the Text File
    echo %Address%
    ::but the above here, echo's back nothing at all,(which then is either echo is off or echo is on) even though %Address% has been set to !Line%x%!
    pause
    ::when i try to use !Line%x%! in my code, like the start code below, it returns nothing instead of the URL
    start %browser% %Address% >nul 2>&1
    start %browser% !Line%x%! >nul 2>&1
    ::neither start code works unfortunately and that's my ISSUE
    ping localhost -n 2 >nul
    goto ReadLines
)
:Completed
::Continue or Whatever...

so my question: Does anyone know why, when echoed, !Line%x%! returns the values it should, but when called uppon for a command such as, start %browser% %Address%, that it returns nothing? BTW you can run the above code just put some link in a txt doc named 'Test.txt' and you'll see my issue for yourself And Sorry if it looks kind of ugly to anyone, i really just threw this together for someone but then ran into this error and need to solve it for this for them. Any Help is wanted, Thanks!


回答1:


@ECHO OFF
setlocal EnableDelayedExpansion
set browser=chrome.exe
set i=0
for %%f in (q20300102.txt) do (
    set i=0
    for /F "delims=" %%l in (%%f) do (
        set /A i+=1
        set line!i!=%%l
        ))
::the above read the contents of Test.txt and saved each line to a different Variable made up of two variables
set x=0
:ReadLines
if %x% gtr %i% (
    goto Completed)
set /a x+=1
set /a odd=%x%%%2
if %odd%==1 (
    set Address=!line%x%!
    echo !Line%x%!
    REM the above echo's back the URL from the Text File
    echo %Address%
    REM but the above here, echo's back nothing at all,(which then is either echo is off or echo is on) even though %Address% has been set to !Line%x%!
    REM pause
    REM when i try to use !Line%x%! in my code, like the start code below, it returns nothing instead of the URL
    ECHO start %browser% %Address%
    ECHO start %browser% !Line%x%!
    REM neither start code works unfortunately and that's my ISSUE
    ECHO ping localhost -n 2
)
goto ReadLines
:Completed
::Continue or Whatever...
GOTO :EOF

Fundamental delayedexpansion problem. In any compound statement (ie. a parenthesised group of statements) any occurrence of %var% is replaced by the value of var at the time the statement is PARSED, and THEN it is executed.

Consequently, when x=1, odd wil be set to 1, the statement group will be parsed and echo %Address% will have %address% replaced by the THEN-current value of address - but address is not yet assigned a value, since the code is only being PARSED - it has not yet been RUN.

Similarly, start %browser% %Address% HAS a value for browser and that value IS substituted, but address is not assigned, so is replaced by [nothing].

At the end of the parenthesised code, yo return to :readlines with x=1. This is incremented and x is assigned 2. This is not odd as far as I've ever experienced, so the entire parenthesised code is skipped and batch proceeds to the following line. In batch, reaching a label does not "end a procedure" so it simply charges on and rockets off to the end of the file.

In my code above, I've

  1. Set the filename to q20300102,txt to suit my system.
  2. Replaced the :: commenting style with REM because in some implementations, a broken-label (::-comment) causes the compound statement to be terminated.
  3. Removed the redirectors to allow the START and PING lines to be ECHOed (and inserted the ECHO keyword)
  4. Moved the GOTO readlines outside of the compound where it will force a loop regardless of whether x is odd or not.

Since you gave no example of a line in your Test.txt, I made my own q20300102.txt which contains:

Address_one
Address_two
Address_three
Address_four
Address_five
Address_six
Address_seven
Address_eight
Address_nine

and ran the above, which yielded

Address_one
ECHO is off.
start chrome.exe 
start chrome.exe Address_one
ping localhost -n 2

Address_three
Address_one
start chrome.exe Address_one
start chrome.exe Address_three
ping localhost -n 2

Address_five
Address_three
start chrome.exe Address_three
start chrome.exe Address_five
ping localhost -n 2

Address_seven
Address_five
start chrome.exe Address_five
start chrome.exe Address_seven
ping localhost -n 2

Address_nine
Address_seven
start chrome.exe Address_seven
start chrome.exe Address_nine
ping localhost -n 2

(I've broken the actual output by iteration for a little more clarity)

So - the response is

Linex content
Address content (note - as it stood when the (statement) was PARSED)
Start statements including the elements just described
Ping statement

So this should get you on the path to solving your problem...




回答2:


In short: "you need to use Delayed Expansion in order to get the value of a variable that was modified inside a block"; this is a basic variable management behavior in Batch files:

if %odd%==1 (
    set Address=!line%x%!        <- "Address" variable was modified inside this block

    - - - - - -

    echo %Address%               <- This not work, you need Delayed Expansion here:
    echo !Address!

    - - - - - -

)



回答3:


1 - Unless you intend to iterate over a group of files, your %%f loop in unnecesary. And if you intend to iterate over a group of files, then the second set i=0 will reset the counter for each file.

2 - As stated in previous answers, when a block of code (everything between opening and closing parenthesis) is readed, every variable is replaced with its current value (at the time of reading the block!) and all block is executed one or more times without changes in the variables, as the code that is being executed does not contain variables, just its value. This behaviour has two exceptions: variables referenced as !var! when delayed expansion is active, and contorl variables declared in for command.

Nothing to add to the other answers on why your code has problems. Magoo and Aacini answers reflect where your problems are based on correct usage of variables with delayed expansion. Every variable modified inside a block needs to be accessed with delayed expansion sintax to retrieve the modified value.

Following code reflects the other option, usage of for variables to elude delayed expansion problems.

@echo off
setlocal EnableDelayedExpansion

    set "i=0"
    for /F "delims=" %%l in (test.txt) do (
        set /A "i+=1"
        set "line!i!=%%l"
    )

    for /l %%x in (1 1 %i%) do (
        set /a "odd=%%x %% 2"
        if !odd!==1 (
            set "Address=!line%%x!"
            echo !line%%x!
            echo !Address!
            echo ---------------
        )
    )


来源:https://stackoverflow.com/questions/20300102/batch-variable-inside-a-variable-not-working-when-called

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!