标题: [原创] 变量延迟的通俗讲解 [打印本页]
作者: hlzj88 时间: 2017-3-30 20:50 标题: 变量延迟的通俗讲解
先声明,也许到目前对这个东西我的理解还不到位,只能作为还没有搞明白变量延迟的坛友一个快速,易懂的理解方式。起码能突破混沌。
想当年,对这个的理解我只有一个字,晕。
我们都知道:一个萝卜一个坑。好多单位也是,一人一岗,假设这个单位人员基本不流动,那么你十几年如一日的看到门卫大爷只能是那个张三。此时,无论谁问你,门卫是谁,你的答案只有张三。
在这里我们就把张三定义为门卫了。
假设某一天因门卫看管不力,造成了财务损失,领导发话了,明儿起,咱们这些人都轮换一天来做门卫工作,大家要自觉自愿,加强监督。那么,此时,有人要问你,今天门卫是谁啊,你能确定吗,不能,好在有值班表,一查,是谁就知道了。
现在的门卫已经不等于张三,他可能是任何一个人,通过查表,才可以确定。
如上,如果一个变量我们定义后,他的值不会发生改变,那么,调用变量时就可以直接调用。但是这个变量定义后,他的值会一直变化,当程序调用变量时,如果不去查表,得到的数据可能是刚开始的数据(前几天的门卫)。显然这个数据可能是不正确的,为了避免这种情况发生,我们就需要去查表。当开启了变量延迟后,程序在每一次调用变量前,都会去查表。以取得正确数据。
开启变量延迟,就是开启了一个让程序查表的开关。
但是我好懒,英语也记不住,变量延迟那么多字母,我都是复制的。为了避免程序出错,变量延迟基本都是复制开启的。个人觉得,让程序忙点,它不累,一秒执行多少命令,不至于在乎一个查表时间,电管够。
理解如上,希望坛子里高手看到后,能不吝赐教。
作者: Nsqs 时间: 2017-3-30 21:42
本帖最后由 Nsqs 于 2017-3-30 22:14 编辑
变量延迟其实很好理解.
首先分清一个概念.什么是全局变量什么是局部变量
全局变量
是指整个程序可见,比如- @echo off
- call:1
- echo %[变量]%
- pause
- exit
- :1
- set "[变量]=可以看见我"
- goto :eof
复制代码
局部变量
是指仅仅局部区域可见,可参见如下效果- @echo off
- (
- call:1
- echo %[变量]%
- )
- pause
- exit
- :1
- set "[变量]=可以看见我"
- goto :eof
复制代码
或者也可以这样- @echo off
- set [变量]=可以看见我
- echo %[变量]%
- pause
复制代码
或这样,变为无法输出的变量- @echo off
- (
- set [变量]=可以看见我
- echo %[变量]%
- )
- pause
复制代码
然后再来谈谈为什么括号被括起来后就无法输出变量的值了呢,那就是作用域的问题,变量被限制在括号内变为不可见
如果想可见必须使用call 即如下写法- @echo off
- (
- set [变量]=可以看见我
- call echo %%[变量]%%
- )
- pause
复制代码
也可以开启变量延迟- @echo off
- setlocal enabledelayedexpansion
- (
- set [变量]=可以看见我
- echo ![变量]!
- )
- pause
复制代码
当然还有复杂一点的变量嵌套写法,比如- @echo off
- set [变量][0]=b
- set [变量][1]=a
- set [变量][2]=t
- for /l %%1 in (0 1 2)do (
- call set /p=%%[变量][%%1]%%<nul
- )
- pause
复制代码
以及- @echo off
- set "[变量][0]=b"
- set "[变量][1]=a"
- set "[变量][2]=t"
- for /l %%1 in (0 1 2)do (
- set /p=%%[变量][%%1]%%<nul
- )
- pause
复制代码
后者显示不出bat3个字,这是为什么呢?
答:因为如果你在变量里嵌套变量,内层的变量就被当作局部处理,而必须开启变量延迟或者调用call 来让外层变量看到内层变量才行
还有一些其他的例子比如- @echo off
- set "[变量]=这是一个例子"
- for /f "tokens=1 delims=:" %%1 in ('^(echo %[变量]%^&echo;^)^|findstr /o ".*"')do set /a n=%%1-3
- for /l %%1 in (0 1 %n%)do (
- call set /p=%%[变量]:~%%1,1%%<nul
- )
- echo;
- pause
复制代码
或者- @echo off
- set "[变量]=这是一个例子"
- for /f "tokens=1 delims=:" %%1 in ('^(echo %[变量]%^&echo;^)^|findstr /o ".*"')do set /a n=%%1-3
- for /l %%1 in (0 1 %n%)do (
- set /p=%[变量]:~%%1,1%<nul
- )
- echo;
- pause
复制代码
最后一例- @echo off
- for /l %%1 in (9 -1 1)do (
- call set n=%%n%%%%1
- )
- call:1 %n%
- pause
- exit
- :1
- for /l %%i in (1 1 9)do (
- call set/p=%%%%i <nul
- )
- goto :eof
复制代码
不用call显然也无法输出- @echo off
- for /l %%1 in (9 -1 1)do (
- call set n=%%n%%%%1
- )
- call:1 %n%
- pause
- exit
- :1
- for /l %%i in (1 1 9)do (
- set/p=%%%i <nul
- )
- goto :eof
复制代码
疑问:
1.为什么变量在for内赋值后无法得到其值或计算错误
答:因为变量在for内是属于局部变量
2.为什么变量在if内无法进行布尔运算
答:因为if的条件判断必须开启变量延迟,无法使用call if XXX
3.为什么一定要使用!(开启变量延迟)呢?
答:一般来讲尽量不开.一个是在写的过程中会麻烦一点,另一个就是在很多时候变量延迟带来的麻烦地方也不少
就不一一举例了.比如输出一段字符串时必须用^转义(即^!)
4.有些时候使用!xx:~!yy!,1!无效怎么办?
答:这种写法是错误的,只有两种写法,根据实际情况来决定,一个是call echo !xx:~%%yy%%,1! ,另一个是
call echo %%xx:~!yy!,1%%.具体一般用前者还是后者,是看情况的.作用不同的时候前后其中一个肯定用不了,
不过多用于后者的情况比较多.然后就是这种混合写法前提是必须开启变量延迟.
5.for循环中的%%X变量和call %%X%%容易搞混,或代码写多了万一分不清怎么办?
答:自己写的程序想到哪写到哪,应该不会犯这种错误,要分清他们哪个是循环中的变量哪个是普通的变量很简单,
for中的变量是%%A-Z1-9 一个字符在后,并且只能用一个字表示.分清这点就可以使用call了
最后要说的就是开启变量延迟或者用call的效果是一样的,只是call的使用上比较强大.既能call:标签也能call程序、也能调用变量.
如果你耐心看完和测试以上所有的代码并加以分析和理解,你会发现其实很简单.理解上面所有代码你就可以处理很多问题了
作者: hlzj88 时间: 2017-3-31 06:20
谢谢Nsqs,需要按你说的做,从中体会理解。
作者: ai20110304 时间: 2017-3-31 10:39
That's great
欢迎光临 批处理之家 (http://bbs.bathome.net/) |
Powered by Discuz! 7.2 |