我想知道有没有办法检查批处理文件中是否存在标签?
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)
它仍然没有引用引用的标签名称,只是为了命名一个失败点.
这是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.