为什么CALL在此脚本中打印GOTO帮助消息?为什么后面的命令执行两次? [英] Why CALL prints the GOTO help message in this script?And why command after that are executed twice?

查看:143
本文介绍了为什么CALL在此脚本中打印GOTO帮助消息?为什么后面的命令执行两次?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这里有一个有趣的话题


  1. 您可以使用具有双倍展开的特殊符号访问标签。

  2. 不能使用包含 /?的标签,因为 GOTO CALL
    $ b

      @echo off 

    setlocal enableDelayedExpansion
    setlabel = /?

    call:%% label %%
    echo ==测试消息以检查是否执行CALL或GOTO(或两者都不)命令==

    exit / b 0

    :/?
    echo == CALL或GOTO已执行==
    退出/ b 0

    并输出:

     将cmd.exe定向到批处理程序中的标记行。 

    GOTO标签

    label将批处理程序中使用的文本字符串指定为标签。

    您自己在一行上键入标签,以冒号开头。

    如果启用命令扩展GOTO更改如下:

    GOTO命令现在接受目标标签:EOF,它将控制
    传送到当前批处理结束脚本文件。这是一个简单的方法来
    退出批处理脚本文件,而不定义标签。类型CALL /?为
    描述CALL命令的扩展,使这个功能
    有用。
    ==测试消息以检查是否执行CALL或GOTO(或两个)命令==
    ==测试消息以检查是否执行CALL或GOTO(或两者都不)==

    CALL 后的代码执行两次? ?



    EDIT



    这对我来说更难以解释:

      @echo off 

    setlocal enableDelayedExpansion
    setlabel =
    set / ax = 1
    call:%% label %%> nul

    set / ax = x + 1
    echo ---
    echo - %x% -
    echo ---

    退出/ b 0

    :/?
    echo == CALL或GOTO已执行==
    echo ==第一个参数:%1 ==
    exit / b 0
    pre>

    输出为:

      --- 
    -3-
    ---

    调用<$ c后的代码$ c> CALL 确保执行两次,但第一次运行的输出可以在同一行重定向?

    解决方案

    我总是感到惊讶,你仍然发现从来没有想到的东西来测试。



    与Aacini相反,我不认为:/?这里作为有效的标签。 >
    否则应该找到这样的标签。



    我假设 CALL 的堆栈推送器函数,然后只需使用 GOTO 跳转到标签。



    扩展命令本身未检测到 /?,而是 GOTO 命令。

    goto 只显示帮助信息并完成,但由于 / code>已经将文件位置推送到堆栈,它的工作原理就像调用这个文件位置,然后返回到同一位置!

      sethelp = ^ /? 
    call:myLabel %% help %%

    这也显示了帮助, code> GOTO:myLabel /?会做。

    但是这不会

      sethelp = /? 
    call:myLabel %% help %%

    我想,GOTO只获取标签由CALL解析,其他参数移动到%1,%2,...



    可以解释为什么只有标签可以使用延迟展开两次

      @echo off 
    setlocal EnableDelayedExpansion
    setlabel = myLabel
    setpointer = ^!label ^!
    call:!pointer!
    exit / b

    :myLabel
    echo it works


    Here's one interesting thread. And I tried to play with the two things discussed there.

    1. You can access labels with special symbols with double expansion.
    2. Labels that contain /? cannot be used because GOTO and CALL prints their help messages instead of execution.

    And here's the result:

    @echo off
    
    setlocal enableDelayedExpansion
    set "label=/?"
    
        call :%%label%%
        echo == Test message to check if the CALL or GOTO ( or neither ) command is executed  ==
    
    exit /b 0
    
    :/?
        echo == CALL or GOTO has been executed ==
    exit /b 0
    

    And the output:

    Directs cmd.exe to a labeled line in a batch program.
    
    GOTO label
    
      label   Specifies a text string used in the batch program as a label.
    
    You type a label on a line by itself, beginning with a colon.
    
    If Command Extensions are enabled GOTO changes as follows:
    
    GOTO command now accepts a target label of :EOF which transfers control
    to the end of the current batch script file.  This is an easy way to
    exit a batch script file without defining a label.  Type CALL /?  for a
    description of extensions to the CALL command that make this feature
    useful.
    == Test message to check if the CALL or GOTO ( or neither ) command is executed  ==
    == Test message to check if the CALL or GOTO ( or neither ) command is executed  ==
    

    And the code after the CALL is executed twice??

    EDIT

    This is even more unexplainable to me:

    @echo off
    
    setlocal enableDelayedExpansion
    set "label=/?"
        set /a x=1
        call :%%label%% >nul
    
        set /a x=x+1
        echo ---
        echo -%x%-
        echo ---
    
    exit /b 0
    
    :/?
        echo == CALL or GOTO has been executed ==
        echo == first argument : %1 ==
    exit /b 0 
    

    The output is:

    ---
    -3-
    ---
    

    The code after the call of the CALL for sure is executed twice, but the output of the first run can be redirected in the same line?

    解决方案

    I'm always surprised, that you still found things that never came to my mind to test.

    Contrary to Aacini, I don't believe that :/? acts here as a valid label.
    Else this should find such a label.

    I suppose that the CALL command is internally composed of a stack pusher function and then just use GOTO to jump to the label.

    And as you are using late expansion the /? isn't detected by the CALL command itself, but by the GOTO command.
    The goto shows only the help info and finished, but as the call has already pushed the fileposition to the stack it works like calling this filepostion and later return to the same location!

    set "help=^ /?"
    call :myLabel%%help%%
    

    This shows also the help, like a GOTO :myLabel /? would do.
    But this one don't

    set "help=/?"
    call :myLabel %%help%%
    

    I suppose, the GOTO gets only the label parsed by the CALL, the other parameters are moved to %1, %2, ...

    And this could explain why only the label can use delayed expansion two times.

    @echo off
    setlocal EnableDelayedExpansion
    set "label=myLabel"
    set "pointer=^!label^!"
    call :!pointer!
    exit /b
    
    :myLabel
    echo it works
    

    这篇关于为什么CALL在此脚本中打印GOTO帮助消息?为什么后面的命令执行两次?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆