bat for语句@echo offfor /l %%i in (1,1,30) do ( echo %%i)pause和@echo offfor /l %%i in (1,1,30) do (set k=%%i echo )pause和@echo offsetlocal enabledelayedexpansionfor /l %%i in (1,1,30) do (set s=%%iecho )pause都一样啊 有什么区别?我现

来源:学生作业帮助网 编辑:作业帮 时间:2024/05/01 03:12:45
bat for语句@echo offfor /l %%i in (1,1,30) do ( echo %%i)pause和@echo offfor /l %%i in (1,1,30) do (set k=%%i echo )pause和@echo offsetlocal enabledelayedexpansionfor /l %%i in (1,1,30) do (set s=%%iecho )pause都一样啊 有什么区别?我现

bat for语句@echo offfor /l %%i in (1,1,30) do ( echo %%i)pause和@echo offfor /l %%i in (1,1,30) do (set k=%%i echo )pause和@echo offsetlocal enabledelayedexpansionfor /l %%i in (1,1,30) do (set s=%%iecho )pause都一样啊 有什么区别?我现
bat for语句
@echo off
for /l %%i in (1,1,30) do (
echo %%i
)
pause

@echo off
for /l %%i in (1,1,30) do (
set k=%%i
echo
)
pause

@echo off
setlocal enabledelayedexpansion
for /l %%i in (1,1,30) do (
set s=%%i
echo
)
pause
都一样啊 有什么区别?我现在想学for语句没学过c“ 静态变量”概念 等 谁给我讲讲for的应用

bat for语句@echo offfor /l %%i in (1,1,30) do ( echo %%i)pause和@echo offfor /l %%i in (1,1,30) do (set k=%%i echo )pause和@echo offsetlocal enabledelayedexpansionfor /l %%i in (1,1,30) do (set s=%%iecho )pause都一样啊 有什么区别?我现
来自批处理之家的解释,我自己学的时候整理的,看看,肯定有用.
变量延迟在for语句中起着至关重要的作用,不只是在for语句中,在其他的复合语句中,它也在幕后默默地工作着,为了突出它的重要性,本节内容在单独的楼层中发出来,希望引起大家的重视.
对于批处理新手而言,“变量延迟”这个概念很可能闻所未闻,但是,它却像一堵横亘在你前进道路上的无形高墙,你感受不到它的存在,但当你试图往前冲时,它会把你狠狠地弹回来,让你无法逾越、无功而返;而一旦找到了越过它的方法,你就会发现,在for的世界里,前面已经是一片坦途,而你对批处理的理解,又上升到了一个新的境界.
例如,你编写了这样一个代码:
@echo off
set num=0echo %num%
pause
你的本意是想对变量num赋值之后,再把这个值显示出来,结果,显示出来的并不是0,而是显示:ECHO 处于关闭状态.之所以会出错,是因为“变量延迟”这个家伙在作怪.
在讲解变量延迟之前,我们需要了解一下批处理的执行过程,它将有助于我们深入理解变量延迟.
1、批处理的执行过程
“自上而下,逐条执行”,我想,这个经典的说法大家都已经耳熟能详了,没事的时候倒着念,也还别有一番古韵呢^_^,但是,我想问大家的是,大家真的深刻地理解了这句话的含义了吗?
“自上而下”,这一条和我们本节的讲解关系不大,暂时略过不说,后一条,“逐条执行”和变量延迟有着莫大的干系,它是我们本节要关注的重点.
很多人往往认为一行代码就是一条语句,从而把“逐条执行”与“逐行执行”等同起来,这就大错特错了.
莫非“逐条执行”里暗藏着玄机?正是如此.
“逐条”并不等同于“逐行”.这个“条”,是“一条完整的语句”的意思,并不是指“一行代码”.在批处理中,是不是一条完整的语句,并不是以行来论的,而是要看它的作用范围.
什么样的语句才算“一条完整的语句”呢?
· 在复合语句中,整个复合语句是一条完整的语句,而无论这个复合语句占用了多少行的位置.常见的复合语句有:for语句、if……else语句、用连接符&、||和&&连接的语句,用管道符号|连接的语句,以及用括号括起来的、由多条语句组合而成的语句块;
· 在非复合语句中,如果该语句占据了一行的位置,则该行代码为一条完整的语句.
例如:
@echo off
set num=0
for /f %%i in ('dir /a-d /b *.exe') do (
set /a num+=1
echo num 当前的值是 %num%
)
echo 当前目录下共有 %num% 个exe文件
dir /a-d /b *.txt|findstr "test">nul&&(
echo 存在含有 test 字符串的文本本件
)||echo 不存在含有 test 字符串的文本文件
if exist test.ini (
echo 存在 test.ini 文件
) else echo 不存在 test.ini 文件
pause
上面的代码共有14行,但是只有完整的语句只有7条,它们分别是:
第1条:第1行的echo语句;
第2条:第2行的set语句;
第3条:第3、4、5、6行上的for复合语句;
第4条:第7行的echo语句;
第5条:第8、9、10行上用&&和||连接的复合语句;
第6条:第11、12、13行上的if……else复合语句;
第7条:第14行上的pause语句.
在这里,我之所以要花这么长的篇幅来说明一行代码并不见得就是一条语句,是因为批处理的执行特点是“逐条”执行而不是“逐行”执行,澄清了这个误解,将会更加理解批处理的预处理机制.
2、预处理
在代码“逐条”执行的过程中,cmd.exe这个批处理解释器会对每条语句做一些预处理工作,这就是批处理中大名鼎鼎的“预处理机制”.
预处理机制:首先,把一条完整的语句读入内存中,不管这条语句有多少行,它们都会被一起读入,然后,识别出哪些部分是命令关键字,哪些是开关、哪些是参数,哪些是变量引用等等.如果代码语法有误,则给出错误提示或退出批处理环境;如果顺利通过,最后,就把该条语句中所有被引用的变量及变量两边的百分号对,用这条语句被读入内存之就已经赋予该变量的具体值来替换.当所有的预处理工作完成之后,批处理才会执行每条完整语句内部每个命令的原有功能.
也就是说:如果命令语句中含有变量引用(变量及紧邻它左右的一对百分号),并且某个变量的值在命令的执行过程中被改变了,即使该条语句内部的其他地方也用到了这个变量,也不会用最新的值去替换它们,因为某条语句在被预处理的时候,所有的变量引用都已经被替换成字符串常量了.
我们了解到:变量值在复合语句内部被改变,不会影响到语句内部的其他任何地方.
看个例子帮助理
@echo off
set /a var=0
for /l %%i in (1,1,5) do (
set /a var=var+100
set temp=%var%
)
echo %temp%
pause
我们的本意是将var这个变量执行5次加100运算,并且把每次运算得到的数值赋值给一个新的变量temp,最终结果用temp输出,在其他语言中我们口头得到结果是500,但是批处理给出我们一个0.
根据预处理机制,我们解释一下:
在执行前,对for语句进行预处理的时候var的值是0,首先所%var%的值进行替换,于是%var%=0,这个值会始终保持不变,于是我们得到最终的结果为0.
3、使用变量延迟
那怎么才能实现我们希望得到的功能呢?
解决办法:使用变量延迟扩展语句,让变量的扩展行为延迟一下,从而获取我们想要的值.
一般说来,延迟变量的扩展行为,可以有如下选择:
· 在适当位置使用 setlocal enabledelayedexpansion 语句,开启变量延迟;
· 在适当的位置使用 call 语句.
其中“变量扩展”就是将使用一对百分号闭合环境变量以完成对其值的替换行为.说得直白一点,所谓的“变量扩展”,实际上就是用具体的值去替换被引用的变量及紧贴在它左右的那对百分号.
①使用 setlocal enabledelayedexpansion 语句
@echo off
setlocal enabledelayedexpansion
set num=0&&echo !num!
Pause

@echo off
setlocal enabledelayedexpansion
set /a var=0
for /l %%i in (1,1,5) do (
set /a var=var+100
set temp=!var!
)
echo !temp!
pause
②使用call语句
@echo off
set num=0&&call echo %%num%%
Pause

@echo off
set /a var=0
for /l %%i in (1,1,5) do (
set /a var=var+100
call set temp=%%var%%
)
echo %temp%
pause
由此可见,如果使用 setlocal enabledelayedexpansion 语句来延迟变量,就要把原本使用百分号对闭合的变量引用改为使用感叹号对来闭合;如果使用call语句,就要在原来命令的前部加上 call 命令,并把变量引用的单层百分号对改为双层. 其中,因为call语句使用的是双层百分号对,容易使人犯迷糊,所以用得较少,常用的是使用 setlocal enabledelayedexpansion 语句(set是设置的意思,local是本地的意思,enable是能够的意思,delayed是延迟的意思,expansion是扩展的意思,合起来,就是:让变量成为局部变量,并延迟它的扩展行为).
四、总结
①、为什么要使用变量延迟?
因为要让复合语句内部的变量实时感知到变量值的变化.
②、在哪些场合需要使用变量延迟语句?
在复合语句内部,如果某个变量的值发生了改变,并且改变后的值需要在复合语句内部的其他地方被用到,那么,就需要使用变量延迟语句.而复合语句有:for语句、if……else语句、用连接符&、||和&&连接的语句、用管道符号|连接的语句,以及用括号括起来的、由多条语句组合而成的语句块.最常见的场合,则是for语句和if……else语句.
③、怎样使用变量延迟?
· 使用 setlocal enabledelayedexpansion 语句:在获取变化的变量值语句之前使用setlocal enabledelayedexpansion,并把原本使用百分号对闭合的变量引用改为使用感叹号对来闭合;
· 使用 call 语句:在原来命令的前部加上 call 命令,并把变量引用的单层百分号对改为双层.
“变量延迟”是批处理中一个十分重要的机制,它因预处理机制而生,用于复合语句,特别是大量使用于强大的for语句中.只有熟练地使用这一机制,才能在for的世界中如鱼得水,让自己的批处理水平更上一层楼.很多时候,对for的处理机制,我们一直是雾里看花,即使偶有所得,也只是只可意会难以言传.希望大家反复揣摩,多加练习,很多细节上的经验,是只有通过大量的摸索才能得到的.
Good Luck!