CMD中goto语句会中断for循环特性详解

这个程序里面由于用到了上篇文章中所说的字符串切割,而用到了Goto强制跳转语句

但是在程序中使用的时候却发现一个错误,当把这个字符切割的代码段如果直接作为非嵌套语句执行正常

但是一旦放到for循环的复合语句中就会发现for循环只执行一次之后for循环就退出了,而且临时变量%%x的值就变成空了

换句话说就是goto跳转和目标地:labe不能同时出现在一个for语句中

例如下示例:

for /f %%i in ("abc") do (
  :show
  echo %%i & pause
  goto :show
)

直接看代码含义很简单就是一直去显示abc这个字符串,但是实际执行结果却是:

只有第一次循环正确的执行的我们想要的结果,显示了abc,但是后面的所有都是显示%i

换句话说,当goto跳转后%i失去了原本for循环的临时遍历变量的作用,成了一个普通的字符串

至于为什么会这样我是这样理解的:

因为goto语句是无条件强制跳转,并且无视程序流程,即不管目标标签地是否是复合语句都会强制去顺着标签地向下执行,也许标签地是主流程语句,也许是其他if的复合语句块,也许是与goto是同属一个复合语句块,如果是跳转到外侧或其他语句块,那么当前for循环肯定是要退出的。

但是CMD是边解释边执行,他没有办法也没有义务去检查goto的标签所在地是在哪,从理论上来讲,如果跳转到主流程没有什么问题,如果跳转到另一复合语句块中肯定目标语句块的临时变量(%i)肯定是无效的,因为根本不知道从什么位置直接跳转过来的,根本没有执行主循环语句,何谈临时变量,临时变量是由主循环语句赋予的。

唯独goto和标签同属一个语句块时临时变量应该起效。但是作为边解释边执行的解释器,压根无法预知下一条根本没有输入的语句的内容。

所以(结论):

在for语句中一旦遇到goto,则cmd认为这是break了,不管你跳转到哪,当前for循环肯定是停止了,那么由for循环赋予的临时变量(%i)也就随之无效了。在刚才的例子中虽然跳转完成了还是在for语句中,但cmd已经认为for循环已经退出,这是独立语句了,而不是复合语句

解决方法:

把要进行goto的语句块写成一个函数,写成一个独立模块,再在for中用Call去调用,就正常了

上面的例子改一下:

for /f %%i in ("abc") do (
  call :show %%i
)

:show
echo %1 & pause
goto :show

结果,如我们想要的,一直去显示abc字符串

—— 原文发表于2012-3-11 08:57

时间: 2024-08-04 01:20:34

CMD中goto语句会中断for循环特性详解的相关文章

oracle中的exists 和not exists 用法详解

oracle中的exists 和not exists 用法详解 有两个简单例子,以说明 “exists”和“in”的效率问题 1) select * from T1 where exists(select 1 from T2 where T1.a=T2.a) ; T1数据量小而T2数据量非常大时,T1<<T2 时,1) 的查询效率高. 2) select * from T1 where T1.a in (select T2.a from T2) ; T1数据量非常大而T2数据量小时,T1>

PHP中__get()和__set()的用法实例详解

PHP中__get()和__set()的用法实例详解 在PHP5中,预定义了两个函数“__get()”和“__set()”来获取和赋值其属性,对每个字段进行set和get的操作.只需要加上两个魔术方法即可 php面向对象_get(),_set()的用法 一般来说,总是把类的属性定义为private,这更符合 现实的逻辑.但是,对属性的读取和赋值操作是非常频繁的,因此在PHP5中,预定义了两个函数“__get()”和“__set()”来获取和赋值其属 性.类似于java中的javabean的操作,

Lua中的模块(module)和包(package)详解1

这篇文章主要介绍了Lua中的模块(module)和包(package)详解,本文讲解了require函数.写一个模块.package.loaded.module函数等内容,需要的朋友可以参考下 前言 从Lua5.1版本开始,就对模块和包添加了新的支持,可是使用require和module来定义和使用模块和包.require用于使用模块,module用于创建模块.简单的说,一个模块就是一个程序库,可以通过require来加载.然后便得到了一个全局变量,表示一个table.这个table就像是一个命

Lua中的模块(module)和包(package)详解

这篇文章主要介绍了Lua中的模块(module)和包(package)详解,本文讲解了require函数.写一个模块.package.loaded.module函数等内容,需要的朋友可以参考下 前言 从Lua5.1版本开始,就对模块和包添加了新的支持,可是使用require和module来定义和使用模块和包.require用于使用模块,module用于创建模块.简单的说,一个模块就是一个程序库,可以通过require来加载.然后便得到了一个全局变量,表示一个table.这个table就像是一个命

SQLServer中服务器角色和数据库角色权限详解

SQLServer中服务器角色和数据库角色权限详解 by e-online 26. 九月 2009 18:55 coming from http://blog.csdn.net/e_online/article/details/4597957 角色 当几个用户需要在某个特定的数据库中执行类似的动作时(这里没有相应的Windows用户组),就可以向该数据库中添加一个角色(role).数据库角色指定了可以访问相同数据库对象的一组数据库用户. 数据库角色的成员可以分为如下几类: Windows用户组或

【转帖】windows命令行中java和javac、javap使用详解(java编译命令)

windows命令行中java和javac.javap使用详解(java编译命令) 更新时间:2014年03月23日 11:53:15   作者:    我要评论 http://www.jb51.net/article/48380.htm 学习一下java 最近重新复习了一下java基础,这里便讲讲对于一个类文件如何编译.运行.反编译的.也让自己加深一下印象 如题,首先我们在桌面,开始->运行->键入cmd 回车,进入windows命令行.进入如图所示的画面: 可知,当前默认目录为C盘User

PDO中获取结果集之fetchColumn()方法详解

fetchCloumn()方法是获取结果集中下一行指定列的值,从结果集中的下一行返回单独的一列.直线电机品牌 那么我们在前面两篇文章<PDO中获取结果集之fetchAll()方法详解>和<PDO中获取结果集之fetch()方法详解>中我们介绍了两种类似的PDO中获取结果集的方法,那么我们接下来跟大家介绍fetchColumn()方法! 下面我们先看下fetchColumn()方法的语法格式如下: 1 string PDOStatement::fetchColumn ([ int $

PDO中获取结果集之fetchAll()方法详解

fetchAll()方法是获取结果集中的所有行,返回一个包含结果集中所有行的二进制数组!大理石机械构件维修厂家 那么在上一篇<PDO中获取结果集之fetch()方法详解>中,我们介绍了fetch()方法获取结果集,我们今天将要介绍的fetchAll()方法与上一个方法fetch()类似,但是该方法只需要调用一次就可以获取结果集中的所有行,并赋给返回的数组(二维). fetchAll()方法的语法格式如下: 1 array PDOStatement::fetchAll ([ int $fetch

day01_linux中与Oracle有关的内核参数详解

linux中与Oracle有关的内核参数详解 在安装Oracle的时候需要调整linux的内核参数,但是各参数代表什么含义呢,下面做详细解析. Linux安装文档中给出的最小值: fs.aio-max-nr = 1048576 fs.file-max = 6815744 kernel.shmall = 2097152 kernel.shmmax = 4294967295 kernel.shmmni = 4096 kernel.sem = 250 32000 100 128 net.ipv4.ip