[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
返回列表 发帖

[原创] 变量延迟的通俗讲解

先声明,也许到目前对这个东西我的理解还不到位,只能作为还没有搞明白变量延迟的坛友一个快速,易懂的理解方式。起码能突破混沌。
想当年,对这个的理解我只有一个字,晕。

我们都知道:一个萝卜一个坑。好多单位也是,一人一岗,假设这个单位人员基本不流动,那么你十几年如一日的看到门卫大爷只能是那个张三。此时,无论谁问你,门卫是谁,你的答案只有张三。
    在这里我们就把张三定义为门卫了。

假设某一天因门卫看管不力,造成了财务损失,领导发话了,明儿起,咱们这些人都轮换一天来做门卫工作,大家要自觉自愿,加强监督。那么,此时,有人要问你,今天门卫是谁啊,你能确定吗,不能,好在有值班表,一查,是谁就知道了。

   现在的门卫已经不等于张三,他可能是任何一个人,通过查表,才可以确定。

如上,如果一个变量我们定义后,他的值不会发生改变,那么,调用变量时就可以直接调用。但是这个变量定义后,他的值会一直变化,当程序调用变量时,如果不去查表,得到的数据可能是刚开始的数据(前几天的门卫)。显然这个数据可能是不正确的,为了避免这种情况发生,我们就需要去查表。当开启了变量延迟后,程序在每一次调用变量前,都会去查表。以取得正确数据。

开启变量延迟,就是开启了一个让程序查表的开关。


但是我好懒,英语也记不住,变量延迟那么多字母,我都是复制的。为了避免程序出错,变量延迟基本都是复制开启的。个人觉得,让程序忙点,它不累,一秒执行多少命令,不至于在乎一个查表时间,电管够。

理解如上,希望坛子里高手看到后,能不吝赐教。
目的,学习批处理

本帖最后由 Nsqs 于 2017-3-30 22:14 编辑

变量延迟其实很好理解.

首先分清一个概念.什么是全局变量什么是局部变量

全局变量
是指整个程序可见,比如
  1. @echo off
  2. call:1
  3. echo %[变量]%
  4. pause
  5. exit
  6. :1
  7. set "[变量]=可以看见我"
  8. goto :eof
复制代码
局部变量
是指仅仅局部区域可见,可参见如下效果
  1. @echo off
  2. (
  3.   call:1
  4.   echo %[变量]%
  5. )
  6. pause
  7. exit
  8. :1
  9. set "[变量]=可以看见我"
  10. goto :eof
复制代码
或者也可以这样
  1. @echo off
  2. set [变量]=可以看见我
  3. echo %[变量]%
  4. pause
复制代码
或这样,变为无法输出的变量
  1. @echo off
  2. (
  3.   set [变量]=可以看见我
  4.   echo %[变量]%
  5. )
  6. pause
复制代码
然后再来谈谈为什么括号被括起来后就无法输出变量的值了呢,那就是作用域的问题,变量被限制在括号内变为不可见

如果想可见必须使用call 即如下写法
  1. @echo off
  2. (
  3.   set [变量]=可以看见我
  4.   call echo %%[变量]%%
  5. )
  6. pause
复制代码
也可以开启变量延迟
  1. @echo off
  2. setlocal enabledelayedexpansion
  3. (
  4.   set [变量]=可以看见我
  5.   echo ![变量]!
  6. )
  7. pause
复制代码
当然还有复杂一点的变量嵌套写法,比如
  1. @echo off
  2. set [变量][0]=b
  3. set [变量][1]=a
  4. set [变量][2]=t
  5. for /l %%1 in (0 1 2)do (
  6.     call set /p=%%[变量][%%1]%%<nul
  7. )
  8. pause
复制代码
以及
  1. @echo off
  2. set "[变量][0]=b"
  3. set "[变量][1]=a"
  4. set "[变量][2]=t"
  5. for /l %%1 in (0 1 2)do (
  6.     set /p=%%[变量][%%1]%%<nul
  7. )
  8. pause
复制代码
后者显示不出bat3个字,这是为什么呢?
答:因为如果你在变量里嵌套变量,内层的变量就被当作局部处理,而必须开启变量延迟或者调用call 来让外层变量看到内层变量才行

还有一些其他的例子比如
  1. @echo off
  2. set "[变量]=这是一个例子"
  3. for /f "tokens=1 delims=:" %%1 in ('^(echo %[变量]%^&echo;^)^|findstr /o ".*"')do set /a n=%%1-3
  4. for /l %%1 in (0 1 %n%)do (
  5.     call set /p=%%[变量]:~%%1,1%%<nul
  6. )
  7. echo;
  8. pause
复制代码
或者
  1. @echo off
  2. set "[变量]=这是一个例子"
  3. for /f "tokens=1 delims=:" %%1 in ('^(echo %[变量]%^&echo;^)^|findstr /o ".*"')do set /a n=%%1-3
  4. for /l %%1 in (0 1 %n%)do (
  5.     set /p=%[变量]:~%%1,1%<nul
  6. )
  7. echo;
  8. pause
复制代码
最后一例
  1. @echo off
  2. for /l %%1 in (9 -1 1)do (
  3. call set n=%%n%%%%1
  4. )
  5. call:1 %n%
  6. pause
  7. exit
  8. :1
  9. for /l %%i in (1 1 9)do (
  10.     call set/p=%%%%i <nul
  11. )
  12. goto :eof
复制代码
不用call显然也无法输出
  1. @echo off
  2. for /l %%1 in (9 -1 1)do (
  3. call set n=%%n%%%%1
  4. )
  5. call:1 %n%
  6. pause
  7. exit
  8. :1
  9. for /l %%i in (1 1 9)do (
  10.     set/p=%%%i <nul
  11. )
  12. 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程序、也能调用变量.

如果你耐心看完和测试以上所有的代码并加以分析和理解,你会发现其实很简单.理解上面所有代码你就可以处理很多问题了

TOP

谢谢Nsqs,需要按你说的做,从中体会理解。
目的,学习批处理

TOP

That's great

TOP

返回列表