【问题标题】:Batch variable inside a variable not working when called变量内的批处理变量在调用时不起作用
【发布时间】:2013-11-30 12:13:33
【问题描述】:

在 Test.txt 内部读取第一行的 URL,还有更多,但这并不重要。

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

所以我的问题是:有谁知道为什么,当回显时,!Line%x%!返回它应该的值,但是当 调用诸如 start %browser% %Address% 之类的命令,它什么也不返回? 顺便说一句,您可以运行上面的代码,只需将一些链接放在名为“Test.txt”的 txt 文档中,您就会自己看到我的问题 对不起,如果它对任何人来说看起来有点难看,我真的只是为某人把它放在一起,但后来遇到了这个错误,需要为他们解决这个问题。需要任何帮助,谢谢!

【问题讨论】:

  • 在这种情况下调试代码时,使用 set 显示所有环境变量的列表。例如,在回显这些值后,在下一行添加一个set,然后在长列表中查找AddressLine%x% 的值

标签: variables batch-file cmd double


【解决方案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

基本delayedexpansion 问题。在任何复合语句(即带括号的语句组)中,任何出现的%var% 都会在语句被解析时被var 的值替换,然后执行它。

因此,当 x=1 时,odd 将被设置为 1,语句组将被解析,echo %Address% 将把 %address% 替换为 address 的 THEN-current 值 - 但 address尚未分配值,因为代码只是被解析 - 它还没有被运行。

同样,start %browser% %Address% 具有 browser 的值,并且该值被替换,但 address 未分配,因此被 [nothing] 替换。

在括号代码的末尾,你用x=1返回:readlines。这是递增的并且x 被分配2。就我所经历的而言,这并不奇怪,因此整个带括号的代码被跳过,批处理继续到下一行。在批处理中,到达一个标签并不会“结束一个程序”,所以它只是简单地充电并飞到文件的末尾。

在我上面的代码中,我已经

  1. 将文件名设置为q20300102,txt 以适应我的系统。
  2. REM 替换了:: 注释样式,因为在某些实现中,损坏的标签(::-comment) 会导致复合语句终止。
  3. 删除了重定向器以允许STARTPING 行被ECHOed(并插入ECHO 关键字)
  4. GOTO readlines 移到复合外,无论x 是否为奇数,都会强制循环。

由于您在 Test.txt 中没有给出任何示例,因此我创建了自己的 q20300102.txt,其中包含:

Address_one
Address_two
Address_three
Address_four
Address_five
Address_six
Address_seven
Address_eight
Address_nine

并运行上面的,这产生了

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

(为了更清楚,我已经通过迭代破坏了实际输出)

所以 - 响应是

Linex 内容
地址内容(注意 - (语句)被解析时的状态)
包括刚刚描述的元素的开始语句
Ping 语句

所以这应该会让你走上解决问题的道路......

【讨论】:

  • 是的,对不起,我确实忘记提到奇怪的事情是在 if 语句之间进行,因为文本文件的一行是 DL 链接,另一行是我告诉的名称它在下载文件后重命名文件。感谢您的回答。
【解决方案2】:

简而言之:“您需要使用延迟扩展来获取在块内修改的变量的值”;这是批处理文件中的基本变量管理行为:

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!

    - - - - - -

)

【讨论】:

  • 就是这样,现在可以完美运行了,谢谢!我只需要将 %Address% 更改为 !Address!
【解决方案3】:

1 - 除非您打算遍历一组文件,否则您的 %%f 循环是不必要的。如果您打算遍历一组文件,那么第二个set i=0 将重置每个文件的计数器。

2 - 如前面的答案所述,当读取一段代码(左括号和右括号之间的所有内容)时,每个变量都被替换为其当前值(在读取该块时!)并执行所有块一次或多次没有改变变量,因为正在执行的代码不包含变量,只包含它的值。这种行为有两个例外:当延迟扩展处于活动状态时引用为!var! 的变量,以及在for 命令中声明的contorl 变量。

对于您的代码为何存在问题的其他答案,没有什么可补充的。 Magoo 和 Aacini 的答案反映了您的问题是基于正确使用具有延迟扩展的变量。块内修改的每个变量都需要使用延迟扩展语法来访问以检索修改后的值。

以下代码反映了另一种选择,即使用for 变量来避免延迟扩展问题。

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

【讨论】:

  • 1- 是的,代码是这样写的,所以它有能力做到这一点,虽然它没有用于多个文件,但我不太了解DelayedExpansion 这有帮助,但我觉得我想得太多了,或者我只是错过了一些东西。
  • 请注意:for 命令中声明的控件“变量”是“可替换参数”,不是变量。准确地将它们称为“变量”会导致类似这样的混淆:在块中扩展的变量值的唯一“例外”是用感叹号括起来的!variables!(启用延迟扩展时)。跨度>
  • @Aacini: 摘自technet: { % variable | %% variable } : Required. Represents a replaceable parameter. Use %variable to carry out for from the command prompt. Use %%variable to carry out the for command within a batch file. Variables are case-sensitive and must be represented with an alpha value, such as %A, %B, or %C. 我认为,在这种情况下,区别甚至不是语义上的
猜你喜欢
  • 1970-01-01
  • 2015-11-29
  • 2021-07-03
  • 2013-10-27
  • 2019-08-29
  • 2022-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-07
相关资源
最近更新 更多