09 Windows批处理之标签和无序执行

打印 上一主题 下一主题

主题 535|帖子 535|积分 1605

在最基本的层面上,标签是一种标识符,它用尽可能少的文字简明地界说了一种产品或一个对象。如果我们没有标签,商业就会停滞不前;杂货店里会摆满一架又一架秘密的罐头产品。晚餐吃什么?它可能是豆类或南瓜派混淆物;我们要打开才能知道。
如果没有标签,批处理就不会陷入如此紊乱的境地,但是您的编码工具箱中将缺少一个用于创建更复杂bat文件的重要工具。到现在为止,我们介绍的每个bat文件、代码片断和清单都是次序执行的。解释器依次解释每一行,起首执行第一个下令,然后执行第二个下令。这种情况一直持续到以下两种情况之一发生:bat文件的最后一个下令被解释,或者出现语法错误使bat文件崩溃。标签允许您以非次序的方式执行批处理下令。在本文中,我将介绍代码中向前和向后分支的概念,根据数据条件重复代码的某些部门,甚至创建一些不是批处理固有的下令。
标签还将为我提供一个很好的机遇来讨论一个非常重要的主题:编码风俗,特别是缩进。
标签

批处理中的标签就是您所期望的那样,一个界说代码块的标签。更具体地说,是标记bat文件中的某个点或位置。标签不是下令,尽管它永久不会被执行,但您很快就会发现它对执行流至关重要。
标签可以包含字母、数字和一些特殊字符,最重要的是,标签必须以冒号开头。奇怪的是,标签的名称可以包含额外的冒号,但不能在第二个位置。例如,这里有一些代码被界说或标记为它的确切功能,查抄特定变量的状态:
  1. :CheckStatus
  2. if /i "%status%" equ "fail" > con echo Failure
  3. if /i "%status%" equ "good" > con echo Success
复制代码
类似地,这段代码处理一个非常基本的中止过程,并被标记为:
  1. :Abort
  2. echo The Process is aborting
  3. exit /B 1
复制代码
我将在后续中讨论退出下令。现在,它只是用来退出bat文件。
界说标签是很简朴的,但是在讨论标签的影响和如何使用它们之前,请允许我说个题外话。
缩进

许多批处理程序员抗拒缩进他们的代码。我不确定为什么,因为我熟悉的其他语言都有缩进的某种约定,如果不是硬性要求的话。我最好的猜测是,它的核心是对语言的根本不尊重,以为批处理是一个实用的麻烦,必须尽快处理,而不考虑可读性,更不用说雅观了。为了使批处理代码获得应有的尊重,我建议所有下令都以两个空格缩进开始。将if下令代码块中的所有逻辑(以及有待讨论的类似布局)再缩进三个空格,嵌套布局的缩进幅度更大。
在关于标签的那节中,这个话题似乎是一个不合逻辑的话题,但现实上,这是一个理想的位置。标签应该稍微突出一点,甚至更突出一点。任何范例的格式良好的文档都有部门、章节、节和/或子节,其中每个部门通常都有某种标题或提示,通过不同的字体、字体大小、加粗、下划线、着色或上述部门或全部的组合,在视觉上从其他文本中脱颖而出。当写入bat文件时,这些选项不可用。我们的武器库已经减少到一个重要的项,即缩进,并对大写和空缺体现认可。
由于标签的第一个字符总是冒号,因此我总是将冒号放在该行的第二个字节中,从而将典范的缩进减少到一个字符。因此,当任何人查看我编写的bat文件时,所有的标签都会突出。我将每行的第一个字符保存为rem下令的开头。例如,这里有一个基本的注释、标签和两个简朴的下令:
  1. rem - This code does something
  2. :DoSomething
  3.   set do=something
  4.   set doMore=somethingElse
复制代码
标签中冒号后面的大写字符也增加了它的突出性。
我希望我不会成为批处理编码约定的斯大林(有观点以为他是一个独裁者)。这只是一个程序员的观点,另有其他经过深思熟虑的约定与我的不同。重要的是代码应该易于阅读。有许多方法可以做到这一点,但是完全没有缩进肯定无法通过测试,即使这个话题袒露了我专制的一面。
goto 下令

现在我们有了界说代码片断的标签,它有什么用呢?一些编码职员现实上使用标签作为临时注释,但标签的真正功能是将流程引导到标签下的代码。这就是goto下令发挥作用的地方,它做了听起来应该做的事变。它指示解释器跳到由标签界说的代码中的某个位置。考虑这两个下令:
  1. goto :Abort
  2. goto :DoSomething
复制代码
goto下令向本文前面界说的:Abort和oSomething标签发送控制。
这并不完全正确;第一个下令将执行发送到中止例程,第二个goto下令永久不会执行。在bat文件中,标签自己可以出现在分支到它的goto下令之前或之后,但重要的是要理解,执行永久不会立即返回到goto下令之后的下令。一旦执行了goto,我们就完全受标签下代码的支配了。
要转到界说为:Abort的标签,也可以使用以下下令:
  1. goto ABORT
复制代码
这里发生了两件事。起首,在goto下令中删除了标签名称中的冒号。我怀疑这是一个早期的错误,微软不会修复以保持向后兼容性。其次,现实的标签只有大写的A,但是goto下令体现整个标签名称大写。
这个例子演示了标签名称是不区分大小写的,就像批处理一样平常操纵一样,而且在goto下令中冒号是可选的。虽然解释器允许这样做,但我以为没有理由将两个标签名称以任何方式区分开来,因为这只会造成混淆。对峙划一性是关键。
在上一篇文章中介绍的call下令也与标签一起使用,但是它的行为与goto下令非常不同。我将在下一篇回到call下令和它们的区别。
正向分支

goto下令向两个方向之一发送控制或流程流;一种是在代码上向前分支。在本例中,三个echo下令向控制台写入文本,但只执行了第一个和第三个echo下令:
  1. > con echo Before GOTO
  2. got :MyLabel
  3. > con echo After GOTO
  4. :MyLabel
  5. > con echo After LABEL
复制代码
不难想象使用这种技术的更复杂的代码。goto下令可以根据if下令的效果有条件地执行,而不是在单个echo下令上进行分支,它可能会跳过更大的代码段。例如,如果某个文件存在或不存在,或者如果检测到错误,您可以跳过一个或多个程序的执行,您可以跳到将中止bat文件执行的代码,跳过其他所有内容。
goto也可以作为跳出循环的工具。不幸的是,我还没有讨论过循环;很快我将详细讨论for下令和循环。但是现在,要理解这个逻辑,你只需要知道这个循环将对listOfNames变量中列出的每个名字执行一次,不管它包含多少个名字:
  1. for %%n in (%listOfNames%) do (
  2.    if /i "%%n" equ "Waldo" goto :FoundName
  3. )
  4. > con echo ** Name Not Found **
  5. :FoundName
复制代码
if下令正在搜刮一个特定的名称。如果找到了,goto下令就跳出循环,跳到最后一行的标签。
这一点之所以重要,有两个原因。起首,它是高效的——如果名称在列表的开头附近找到,那么CPU周期不会浪费在无意义地搜刮列表的其余部门上。更重要的是,如果找到该名称,则永久不会执行echo下令。请注意,逻辑不仅过早地跳出循环,而且还在编写指示未找到名称的消息时进行分支。
逆向分支

前一节中的示例使用goto下令在代码中跳转。接下来,我将看一些反向运行的goto下令的示例。但起首,我已经讨论了我们如何构建更当代语言的某些组件,这些组件不是批处理的显式组成部门(想想布尔值和浮点数),但另有许多其他组件尚未出现。批处理没有while下令,也不支持do…while下令。在其他语言中,while下令执行从零到多次的代码块,直到满足某个条件。一个do…while下令非常相似;唯一的区别是,代码块将在计算条件之前执行一次。让我们在批处理中创建这两个。
while 下令

为了演示批处理while下令的有效性,我们将编写一些代码,将从值中去掉所有前导零,这是任何程序员不希望意外执行八进制算术的须要条件。当第一个字节为0时,while下令可能会执行一段代码,而该代码只会去掉一个前导字节。
  1. :StripLead0s
  2. if "%nbr:~0,1%" equ "0" (
  3.     if "%nbr:~1,2" neq "" (
  4.        set nbr=%nbr:~1%
  5.        goto :StripLead0s
  6. )  )
复制代码
解释器在第一次遇到标签时基本上忽略它,并询问nbr的第一个字符。如果它是零,代码接下来会验证是否有第二个字节——也就是说,这个0现实上是前导。如果两者都为真,则进入代码块,在goto下令将控制发送回If下令之前的标签之前,它将去掉前导0。
如果变量没有前导的0,代码块就不会执行。如果它有一个前导的0,那么代码块就会被执行一次。然后,首字节再次被查抄,由于它不再是0,因此执行流将继承到接下来的任何内容。如果nbr有17个前导的0,那么删除0的代码块执行17次,在首字节被查抄18次之后,执行就继承了。
while这个词没有出现在这个清单中,但是它做了一个得当的while下令所能做的统统。据我所知,这是一个批处理while下令。
重要:
前面的代码片断是我展示的第一个if下令嵌套在另一个if下令内的例子,但是您将在后面的文章中看到更多的嵌套下令。关于编码约定的另一个注意事项是,在该清单中,我将后面的两个右括号堆叠在一行上。这使得代码更加紧凑,特别是当嵌套多层深度时,而且它将重点放在有趣的逻辑上,但我承认我是少数人。大多数批处理程序员将每个右括号与各自的if下令对齐。
  1. :StripLead0s
  2. if "%nbr:~0,1%" equ "0" (
  3.     if "%nbr:~1,2" neq "" (
  4.        set nbr=%nbr:~1%
  5.        goto :StripLead0s
  6.     )
  7. )
复制代码
做你觉得对的事,并对峙做下去。别的,请注意标签名称包含一个数值。如前所述,我们并不局限于字母表中的字母。顺便说一下,这个缩进看起来不错吧?
do...while 下令

批处理 do...while 下令看起来很相似;唯一的区别是主逻辑必须至少执行一次。在具有内置do...while 下令的语言中,条件子句通常出现在布局的末尾(可以理解的是,在主逻辑执行一次之后),批处理也不例外。与while下令相比,主逻辑从if下令代码块内部移动到标签之后和if下令之前。
为了演示,让我们举一个例子,其中textStr变量要右填充至少一个空格,以将其构建为至少25字节的长度。如果原始字符串长度小于25字节,则效果将为25字节;如果它最初至少有25字节长,则会在效果后面添加一个空格。(该字符串可能是要在控制台上体现的一些连接文本的一部门,其中空格填充将对列进行对齐。但当然,我们需要在它和接下来的内容之间留出空间,即使它需要额外的字节。)
正确的填充必须至少完成一次,这实用于 do...while 下令:
  1. :PadRight
  2. set textStr=%textStr% &
  3. if %textStr:~24,1% equ "" goto :PadRight
复制代码
与while下令一样,标签位于大部门代码之前,但核心逻辑紧随厥后,在本例中是用一个空格填充字符串的单个set下令。然后查抄第25个字节。(记住,它是零偏移。)如果它不存在,则goto下令将执行发送回标签,以便在字符串后面添加另一个空格。这个过程一直重复,直到第25个字节被填充,确保字符串至少有25个字节长,而且无论长度如何,至少添加了一个空格。
:eof 标签

一个特殊的标签不是由程序员创建的,而是所有bat文件固有的:eof,它体现文件结束。当以下goto:eof下令在被调用的bat文件的主逻辑中执行时,控制权将返回给调用的bat文件:
  1. > con echo We are about to exit the bat file.
  2. got :eof
  3. > con echo This command will never be executed.
复制代码
在高级bat文件中执行相同的下令将完全停止该历程,即使bat文件中不存在界说为:eof的标签。
如果你有相反的天性并决定界说你自己的:eof标签,解释器会简朴地忽略它,就好像它是一个无意义的注释。在下一篇中,我将进一步探究这个独特的标签,特别是解释器在可调用例程中如何处理goto:eof下令。
变量标签

在没有编译器的语言中工作有一些显着的缺点,但我已经向您展示了一些希望(例如延迟扩展)。另有一个是在执行时在goto下令中界说标签名称的能力,尽管标签自己必须硬编码。为此,设想一年中的每个月都有一个不同的标签。下面体现的是前三个,它们下面没有各自以月份为中心的代码:
  1. :MonthJanuary
  2. :MonthFebruary
  3. :MonthMarch
复制代码
显然,下面的下令将执行到前面代码片断中的一个特定标签:goto :MonthFebruary。
但那都是旧的操纵了。更有趣的是,如果将变量month设置为二月,下面的下令将调用相同的标签:
  1. goto :Month%month%
复制代码
这个goto下令的参数是硬编码的:Month和month变量的值的连接。剖析变量后,下令将执行指向标签:MonthFebruary。对于其他有效月份也是如此,这意味着如果month设置为March,则同一行代码也将变为:MonthMarch。
但是,这确实提出了这样一个问题:当生成的标签名称在bat文件中不存在时,例如,如果month设置为Erele,会发生什么情况。解释器将以下消息写入控制台:
The system cannot find the batch label specified - MonthErele
不幸的是,您将永久不会看到此消息,因为历程将立即崩溃。在下一篇中,您将看到批处理在与call下令一起使用时可以更好地处理错误的标签名称,但是如果您将此技术与goto下令一起使用,请确保参数剖析为有效的标签。
总结

在本文中,我介绍了标签的概念以及如何通过goto下令导航到标签。您学习了如何创建标签,探索了使用标签的技巧,并相识了它们在构建 while 和 do...while 下令中的重要作用。我还介绍了必不可少的 :eof 标签。
但是,您可以通过两种不同的方式导航到标签。下文的大部门内容还将关注标签,以及如何使用标签在bat文件中创建可调用的案例。我还将详细介绍如何从一个bat文件中调用另一个bat文件,这是一个关键主题,因为您开始创建对于单个bat文件来说过于复杂的项目。
本文由博客一文多发平台 OpenWrite 发布!

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

悠扬随风

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表