![]() |
中国DOS联盟-- 联合DOS 推动DOS 发展DOS --联盟域名:www.cn-dos.net 论坛域名:www.cn-dos.net/forum |
| 游客 | 登录 | 注册 | 会员 | 搜索 | 中国DOS联盟 |
|
中国DOS联盟论坛 现在时间是 2026-08-29 08:53 |
共 47,816 主题排行 / 349,916 发帖 / 今日 0 篇 / 48,265 会员排行 |
| DOS批处理 & 脚本技术(批处理室) » SOS!!!!!!请教关于变量延迟!! |
| 可打印版本 1,627 / 8 |
| 第1楼 yuanzijia08 | 发表于 2006-11-04 14:30 |
| 初级用户 发帖 30 积分 78 来自 湖南湘潭 | |
|
SOS!!!!!!请教关于变量延迟!! 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楼 yuanzijia08 | 发表于 2006-11-04 14:35 |
| 初级用户 发帖 30 积分 78 来自 湖南湘潭 | |
|
@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楼 namejm | 发表于 2006-11-04 16:16 |
| 荣誉版主 发帖 1,737 积分 5,226 来自 成都 | |
|
本版精华有这个问题的答案,何必要到外面去找呢?请看:什么情况下该使用变量延迟?
|
|
| 第4楼 yuanzijia08 | 发表于 2006-11-04 22:47 |
| 初级用户 发帖 30 积分 78 来自 湖南湘潭 | |
|
精华版的教程绝对不适合初学者 我是看了好多遍才来问的 我个人觉得还是要以一个事例来分析更好
我先假设程序实在这样的:(比原程序少了个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楼 namejm | 发表于 2006-11-04 23:07 |
| 荣誉版主 发帖 1,737 积分 5,226 来自 成都 | |
|
既然用了 !m! 的格式,也就意味着开启了变量的延迟功能,所以,setlocal EnableDelayedExpansion 语句绝对不能少,否则,CMD是无法解析 !m! 的。
|
|
| 第6楼 willsort | 发表于 2007-01-20 08:32 |
| 元老会员 发帖 1,512 积分 4,432 | |
|
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 ] |
|
| 第7楼 electronixtar | 发表于 2007-01-20 08:34 |
| 铂金会员 发帖 2,672 积分 7,493 | |
|
沙发,占个位置瞻仰willsort的帖子
[ Last edited by electronixtar on 2007-1-20 at 08:41 AM ] |
|
| 第8楼 vkill | 发表于 2007-01-20 08:44 |
| 金牌会员 发帖 1,744 积分 4,103 来自 甘肃.临泽 | |
|
willsort 的帖子看了受益非浅
|
|
| 第9楼 everest79 | 发表于 2007-01-20 09:03 |
| 金牌会员 发帖 1,127 积分 2,564 | |
|
有好些东西,你明白,但就讲不出来,这就是工匠与大师的区别
-------小泥水匠everest79 |
|
|
[ 联系联盟系统管理团队 -
中国DOS联盟 -
标准版 ] Sponsored by ifanr Inc | © 2001–2023 |