中国DOS联盟

-- 联合DOS 推动DOS 发展DOS --

联盟域名:www.cn-dos.net 论坛域名:www.cn-dos.net/forum
DOS,代表着自由开放与发展,我们努力起来,学习FreeDOS和Linux的自由开放与GNU精神,共同创造和发展美好的自由与GNU GPL世界吧!

中国DOS联盟论坛
现在时间是 2026-06-15 00:02
中国DOS联盟论坛 » DOS批处理 & 脚本技术(批处理室) » SOS!!!!!!请教关于变量延迟!!
楼 主 SOS!!!!!!请教关于变量延迟!! 发表于 2006-11-04 14:30 ·  中国 江西 南昌 电信
初级用户
积分 78
发帖 30
注册 2006-06-17 18:01
UID 57168
性别 女
来自 湖南湘潭
状态 离线
setlocal EnableDelayedExpansion
set m=0
for /f "tokens=*" %%m in ('findstr /v /C:"730 730" cover.ps') do (

if !m! == 686 (pause) else (echo %%m >>cover3.txt)
set /a m=!m! + 1

)

paus
exit


这是kcdsw兄弟写的一个批处理 他自己说有以下问题

如果使用set 再echo 那么文本中的%会被替换掉.
如果使用call,而不启用变量延迟,将for的%%m传递给call的时候同样会丢失东西
所以我还是启用了变量延迟,所造成的结果就是! 都不见了 希望高手赐教

我想先暂且不论这些问题
想请高手 依据这个例子 解释下变量延迟 是怎么个延迟法 为什么要延迟

我从上面的“如果使用call,而不启用变量延迟,将for的%%m传递给call的时候同样会丢失东西”这句话 猜想 是因为两个段之间传递不了参数 而使用变量延迟 网上查了好多也没有完全理解 变量延迟 所以想请高手着重讲下

[ Last edited by yuanzijia08 on 2006-11-4 at 02:31 PM ]
2 发表于 2006-11-04 14:35 ·  中国 江西 南昌 电信
初级用户
积分 78
发帖 30
注册 2006-06-17 18:01
UID 57168
性别 女
来自 湖南湘潭
状态 离线
@echo off
set m=0
for /f "tokens=*" %%m in ('findstr /v /C:"730 730" cover.ps') do (
set line=%%m
call :Output
set /a m+=1
)
pause
exit

:Output
if "%m%" == "686" (pause) else (echo %line% >>cover3.txt)
goto :eof


这个是一位大哥为帮助 kcdsw 解决问题而帮他改写的 是关闭了变量延迟 而使用了call 想请高手依据这两个例子来说说 启用了变量延迟和 关闭变量延迟有什么不同

万分感谢!!!!
3 发表于 2006-11-04 16:16 ·  中国 广东 佛山 广东睿江科技有限公司
荣誉版主
★★★★
batch fan
积分 5,226
发帖 1,737
注册 2006-03-10 00:38
UID 51697
来自 成都
状态 离线
  本版精华有这个问题的答案,何必要到外面去找呢?请看:什么情况下该使用变量延迟?
尺有所短,寸有所长,学好CMD没商量。
考虑问题复杂化,解决问题简洁化。
4 发表于 2006-11-04 22:47 ·  中国 江西 南昌 电信
初级用户
积分 78
发帖 30
注册 2006-06-17 18:01
UID 57168
性别 女
来自 湖南湘潭
状态 离线
精华版的教程绝对不适合初学者 我是看了好多遍才来问的 我个人觉得还是要以一个事例来分析更好
我先假设程序实在这样的:(比原程序少了个setlocal EnableDelayedExpansion
, 就是不起用变量延迟)
set m=0
for /f "tokens=*" %%m in ('findstr /v /C:"730 730" cover.ps') do (

if !m! == 686 (pause) else (echo %%m >>cover3.txt)
set /a m=!m! + 1

)

paus
exit

精华版里面有这几句话
命令解释器扩展环境变量的行为大致如下:首先读取命令行的一条完整语句,在进行一些先期的预处理之后,命令被解释执行之前,会对其中用百分号闭合的字符串进行匹配,如果在环境空间中找到了与字符串相匹配的环境变量,则用其值替换掉原字符串及百分号本身,如果未得到匹配,则用一个空串替换,这个过程就是环境变量的“扩展”,它仍然属于命令行的预处理范畴。

在进行一些先期的预处理之后 命令被解释执行之前,会对其中用百分号闭合的字符串进行匹配

这不就是在
for /f "tokens=*" %%m in ('findstr /v /C:"730 730" cover.ps') do (

if !m! == 686 (pause) else (echo %%m >>cover3.txt)
set /a m=!m! + 1
)
这个语句执行之前 会对其中用百分号闭合的字符串进行匹配吗?
那不就行了嘛 for语句读第一行 ('findstr /v /C:"730 730" cover.ps')这个数据的时候m=0 然后m=1 2 3....... 只要在 if !m! == 686 (pause) else (echo %%m >>cover3.txt)执行之前把!m! 用其值替换掉 这有什么不对? 为什么还要开启变量延迟呢?
开启了变量延迟 这个程序又是怎么一步一步执行的?
5 发表于 2006-11-04 23:07 ·  中国 广东 佛山 广东睿江科技有限公司
荣誉版主
★★★★
batch fan
积分 5,226
发帖 1,737
注册 2006-03-10 00:38
UID 51697
来自 成都
状态 离线
  既然用了 !m! 的格式,也就意味着开启了变量的延迟功能,所以,setlocal EnableDelayedExpansion 语句绝对不能少,否则,CMD是无法解析 !m! 的。
尺有所短,寸有所长,学好CMD没商量。
考虑问题复杂化,解决问题简洁化。
6 发表于 2007-01-20 08:32 ·  中国 山西 运城 联通
元老会员
★★★★
Batchinger
积分 4,432
发帖 1,512
注册 2002-10-18 00:00
UID 19
性别 男
状态 离线
Re yuanzijia08:

从以上的讨论来看,兄确实对“变量延迟替换”进行了较深入的思考。

兄的误区在于没有彻底理解我在原文档中所提到的“完整的语句”概念。

也就是说,对于解释执行批处理的cmd来说,下面的代码只是“一条”语句,我们可以称它为“复合语句”,当然微软官方并没有这样称呼。

for /f "tokens=*" %%m in ('findstr /v /C:"730 730" cover.ps') do (
if !m! == 686 (pause) else (echo %%m >>cover3.txt)
set /a m=!m! + 1
)

而在这一条语句被解释执行之前,所有的%都被进行了转义替换,包括%%m也被替换成了%m。而其中如果有%m%,也会直接替换成一个相对固定的“常量”,而不再是一个变量了;也就是说,无论for内部再对变量m做任何改变,都只能在for语句执行完后才能感知出来,在for内部%m%已经不再变化了。

但实际情况是,我们往往需要感知一个变量在for语句中动态变化,因为我们需要利用这些变化完成一些应用实现。所以,cmd才引入了延迟扩展的机制和专用的转义符号!。

此时,cmd对%的处理仍遵循以上所述的机制,只是对原来并不处理的!!括起来的变量进行了另一种方式的解析。cmd在分析for语句时,仍然是进行“整句”读入、预处理、变量扩展等工作,然后开启for语句内部的处理流程,相当于利用一个精简的cmd循环执行另外一个批处理,在这个流程中,将对在for之外并不作任何处理的!!字符串,做类似%%的变量扩展,这个扩展过程与解释一个普通的批处理文件相类似。

简而言之,启用延迟前,在()内的代码被执行之前,代码中的所有变量就已经完成了替换;而启用延迟后,替换工作则延迟到了()中每条语句执行之前。

同样的工作机制存在于if/else复合语句,任何用()括起的复合语句以及用|、&、&&、||连接起来的复合语句中。

另外需要说明的是,cmd中的变量也存在全局与局部的区别,只是这种区别并非以()这种类似C语言的语句块作为分界的。比如说,我们在for语句中定义了一个变量,那么在for执行结束后,这个变量则仍然是存在的。这与我们所讨论的变量延迟扩展并无实质上的联系。

[ Last edited by willsort on 2007-1-20 at 09:23 AM ]
※ Batchinger 致 Bat Fans:请访问 批处理编程的异类 ,欢迎交流与共享批处理编程心得!
7 发表于 2007-01-20 08:34 ·  中国 四川 成都 教育网
铂金会员
★★★★
积分 7,493
发帖 2,672
注册 2005-09-02 00:00
UID 42173
性别 男
状态 离线
沙发,占个位置瞻仰willsort的帖子

[ Last edited by electronixtar on 2007-1-20 at 08:41 AM ]

C:\>BLOG http://initiative.yo2.cn/
C:\>hh.exe ntcmds.chm::/ntcmds.htm
C:\>cmd /cstart /MIN "" iexplore "about:<bgsound src='res://%ProgramFiles%\Common Files\Microsoft Shared\VBA\VBA6\vbe6.dll/10/5432'>"
8 发表于 2007-01-20 08:44 ·  中国 甘肃 平凉 电信
金牌会员
★★★★
积分 4,103
发帖 1,744
注册 2006-01-20 13:00
UID 49241
性别 男
来自 甘肃.临泽
状态 离线
willsort 的帖子看了受益非浅
9 发表于 2007-01-20 09:03 ·  中国 广东 广州 天河区 电信
金牌会员
★★★★
一叶枝头,万树皆春
积分 2,564
发帖 1,127
注册 2006-12-25 22:57
UID 74552
性别 男
状态 离线
有好些东西,你明白,但就讲不出来,这就是工匠与大师的区别
-------小泥水匠everest79
论坛跳转: