检查标签是否存在cmd

Jam*_*mie 4 cmd batch-file

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

If %input%=ABC (  
  If Label ABC Exists (
    Goto ABC
  )
)
Run Code Online (Sandbox Code Playgroud)

我怎样才能做到这一点?任何帮助将不胜感激.

MC *_* ND 10

findstr /i /r /c:"^[ ]*:%input%\>" "%~f0" >nul 2>nul && goto %input%
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

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

X=;=:test
    echo Hello
Run Code Online (Sandbox Code Playgroud)

不,这不是一个有效的行,如果解析器尝试执行标签行,将发生"命令无法识别"错误,BUT 是一个有效的标签来调用或转到.

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

:test arguments
:test:arguments
:test>arguments
:test<arguments
:test&arguments
Run Code Online (Sandbox Code Playgroud)

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

当然,这两个"问题"可能同时发生

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

< ;;:test:;; > This WORKS 
    echo Hello
Run Code Online (Sandbox Code Playgroud)

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%
Run Code Online (Sandbox Code Playgroud)

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

  • 使用单词边界术语的好主意,但在这种情况下它不能很好地工作.FINDSTR认为非字符字符的许多字符在标签内有效.一个例子是`#`.例如,`:label #`是一个有效的标签,你的搜索将错误地匹配`label`,而没有尾随的`#`,因此当GOTO失败时会导致致命的错误.所有其他要点都是有效的 - 实际的解决方案是忽略它们.只是不要在你的脚本中使用这样的奇怪标签:-) (2认同)

dbe*_*ham 7

这是MC ND答案的精致,更强大的版本.(原始答案,他的编辑解决了许多这些相同的观点).

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

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

findstr /ri /c:"^ *:%input% " /c:"^ *:%input%$" "%~f0" >nul 2>nul && goto %input%
Run Code Online (Sandbox Code Playgroud)

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

  • 标签之前可以出现以下任何字符 - , ; = <space> <tab> <0x255>.它们都在标签之前被视为空格.但上面的搜索只允许<space>.甲[class]表达可以使用,但包括<tab><0x255>可以是笨拙.

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

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

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

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