检查标签是否存在cmd

时间:2014-01-25 08:54:28

标签: batch-file cmd

我想知道有没有办法检查批处理文件中是否存在标签?

If %input%=ABC (  
  If Label ABC Exists (
    Goto ABC
  )
)

我该怎么做? 任何帮助将不胜感激。

5 个答案:

答案 0 :(得分:9)

findstr /i /r /c:"^[ ]*:%input%\>" "%~f0" >nul 2>nul && goto %input%

搜索当前批处理文件中的标签,如果没有错误级别,则标签存在

编辑 - 我意识到我处理标签结束的方式有错误,并且要编辑答案(它已经被编辑了)我看到了dbenham的声音。他看到了错误并纠正了它。谢谢。一如既往的好答案,但这比你所曝光的更糟糕。

在这一刻我只有一个XP来测试,但这对我有用。如果有人可以在以后的Windows版本上测试,请。

第一个问题:标签的开头。像往常一样dbenham是正确的,并且集合[;=,<space><tab>0xFF]中的任何字符都可以在标签的冒号之前,单个或重复。但是,只要它是该行的第一个字符,并且它不重复,几乎任何字符都可以在标签的冒号之前(一个例外是其他冒号)。因此,以下内容可以正常运行

    call :test
    goto :test
    echo this will not be echoed

X=;=:test
    echo Hello

不,这不是有效行,如果解析器尝试执行标签行,将发生“命令无法识别”错误,但是一个有效标签来调用或转到。< / p>

第二个问题:标签的结尾。正如dbenham所确定的那样,当标签用于定义函数/过程时,我们大多数人都会放置一个空格和参数列表。这是我意识到的错误以及我原来的答案中已经纠正的错误。但是,空格(显然是行尾)不是标签名称后唯一允许的字符。因此,在上一个示例中,以下任何标签都可以使用

:test arguments
:test:arguments
:test>arguments
:test<arguments
:test&arguments

是的,在这种情况下,它们是解析器的有效命令,并且是有效标签

当然,这两个“问题”可以同时发生

    call :test
    goto :test
    echo this will not be echoed

< ;;:test:;; > This WORKS 
    echo Hello

POST EDIT 1 - 似乎所有这些工作都是在几年前在dostips.com上完成的。感谢所有编写评论中引用的exaustive列表的人。下次,我会先搜索。

POST EDIT 2 - 我一直在尝试处理findstr的限制以包括所有情况。好吧,没有办法。有太多的限制,从在正则表达式中包含0xff字符的不可能性开始。

对于一个强大而简单的解决方案,dbenham的答案是最佳选择。

更强大,但仍然不完整,没有防弹版,比dbenham的答案更复杂

@echo off

    for /l %%i in (1 1 10) do (
        call :testLabelExist "test%%i" && echo Label [test%%i] exist || echo Label [test%%i] does not exist
    )
    exit /b

:test1
 :test2
    :test3
x:test4
::test5
:test6:
:test7#
 :test8 parameters
    :test9 parameters
:test10:myData


:testLabelExist
    for /f "delims=" %%t in (
        'forfiles /p "%~dp0." /m "%~nx0" /c "cmd /d /c @echo 0x09"'
    ) do (
        findstr /i /m /r /c:"^[^:]*[ %%t]*:%~1[ %%t:;,=+]" /c:"^[^:]*[ %%t]*:%~1$" "%~f0" >nul 2>nul 
    )
    exit /b %errorlevel%

它仍然没有引用引用的标签名称,只是为了命名一个失败点。

答案 1 :(得分:7)

这是MC ND answer的精致,更强大的版本。 (原始答案,他的编辑解决了许多相同的问题)。

标签不区分大小写,因此搜索应该不区分大小写。

有效标签可能在标签后面有其他文字,因此需要进行两次搜索。附加文本经常用作文档。例如::label documentation仍然是有效标签。

findstr /ri /c:"^ *:%input% " /c:"^ *:%input%$" "%~f0" >nul 2>nul && goto %input%

上述情况应该适用于大多数情况,但有一些不太可能导致其失败的条件。

  • 以下任何字符都可以显示在标签之前 - , ; = <space> <tab> <0x255>。它们都在标签之前被视为空格。但上面的搜索仅允许<space>。可以使用[class]表达式,但包括<tab><0x255>可能会很尴尬。

  • 以类似的方式,标签可以由<space>以外的某些字符(不同的列表)终止。

  • 标签可以包含正则表达式元字符。

  • FINDSTR $锚点仅将<CR><LF>识别为行尾,因此如果脚本使用Unix样式<LF>行结尾,搜索可能会失败。

    < / LI>

可以改进搜索以处理上述大多数情况。但是,简单地避免代码中的这些条件就更简单了。我不认为使用单个FINDSTR定义防弹搜索是不可能的。防弹搜索需要至少两个FINDSTR,并且必须使用/G:file选项 - yuck。

答案 2 :(得分:2)

请尝试以下代码:

echo off
set "label=sub"
REM next line to reset errorlevel to zero:
(call )
call :%label% 2>nul || (echo %label% not found & exit /b 1) 
echo back from %label%
Exit /b 0

:sab
echo here we are

答案 3 :(得分:0)

首先,我将重新考虑所有内容,每次创建标签时,我都会在“常量或变量区域”中到达顶部,并预定义文件中的每个标签...因此在编写之后,我会去手动检查所有标签,然后做一个

for %%l in ( :label1 :label2 :label3 :label4 :EOF ) do set x_labelexistconst_%%l=.

其中:label1:label2:label3都是目不转睛并且手动输入的-就像所有语言一样,都认为CMD要求在使用之前声明项目,但是如果真的很懒,则可以使用findstr使其自动化带有子例程示例,并改为这样一行:

for /F "tokens=1" %%l in ( 'findstr /i /r /c:"^[ ]*:[a-z0-9]*" "%~f0"' ) do set x_labelexistconst_%%l=.

在代码中使用那些加载的变量数组中的任一个

if defined x_labelexistconst_%input% goto %input%
if defined x_labelexistconst_%input% call %input%

…这种方法的优点是不会调用,然后使用新的findstr“ EACH AND EVERYTIME”进行了“ if exist label”,但是您只需在开始时就执行“ ONCE”预加载标签的列表/数组/构造。

我认为该选项还具有能够执行&& ||的优势。在goto调用之后,因为不使用错误级别来检查标签

if defined x_labelexistconst_%input% (call %input% && echo call ok || echo call bad)

最终用findstr和CALL和GOTO搜索文件(它们会重新读取原始的bat文件等)都是非常慢的命令,避免使用它们或将它们限制为一次或永远不会是bat文件的最佳选择-尤其是在bat文件可能很大的慢速网络连接。并使整个脚本更小,更容易理解。

我没有调试或测试很多,但这似乎是一个更好的主意。

答案 4 :(得分:0)

如果将此添加到函数顶部:

如果“%〜1” ==“测试” goto:eof

您可以使用它来检查您的功能是否存在:

call:myFunction test 2> nul

如果%errorlevel%== 0,请致电:myFunction

示例:

call :myFunction test 2>nul
if "%errorlevel%" == "0" (call :myFunction) else (echo function does not exist)
goto:eof

:myFunction
    if "%~1" == "test" goto:eof
    echo Function exists
goto:eof