我想知道有没有办法检查批处理文件中是否存在标签?
If %input%=ABC (
If Label ABC Exists (
Goto ABC
)
)
我该怎么做? 任何帮助将不胜感激。
答案 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>
行结尾,搜索可能会失败。
可以改进搜索以处理上述大多数情况。但是,简单地避免代码中的这些条件就更简单了。我不认为使用单个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