|
yuanzijia08
初级用户
积分 78
发帖 30
注册 2006-6-17 来自 湖南湘潭
状态 离线
|
『楼 主』:
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 ]
|
|
2006-11-4 14:30 |
|
|
yuanzijia08
初级用户
积分 78
发帖 30
注册 2006-6-17 来自 湖南湘潭
状态 离线
|
『第
2 楼』:
@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 想请高手依据这两个例子来说说 启用了变量延迟和 关闭变量延迟有什么不同
万分感谢!!!!
|
|
2006-11-4 14:35 |
|
|
namejm
荣誉版主
batch fan
积分 5226
发帖 1737
注册 2006-3-10 来自 成都
状态 离线
|
『第
3 楼』:
本版精华有这个问题的答案,何必要到外面去找呢?请看:什么情况下该使用变量延迟?
|
尺有所短,寸有所长,学好CMD没商量。
考虑问题复杂化,解决问题简洁化。 |
|
2006-11-4 16:16 |
|
|
yuanzijia08
初级用户
积分 78
发帖 30
注册 2006-6-17 来自 湖南湘潭
状态 离线
|
『第
4 楼』:
精华版的教程绝对不适合初学者 我是看了好多遍才来问的 我个人觉得还是要以一个事例来分析更好
我先假设程序实在这样的:(比原程序少了个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! 用其值替换掉 这有什么不对? 为什么还要开启变量延迟呢?
开启了变量延迟 这个程序又是怎么一步一步执行的?
|
|
2006-11-4 22:47 |
|
|
namejm
荣誉版主
batch fan
积分 5226
发帖 1737
注册 2006-3-10 来自 成都
状态 离线
|
『第
5 楼』:
既然用了 !m! 的格式,也就意味着开启了变量的延迟功能,所以,setlocal EnableDelayedExpansion 语句绝对不能少,否则,CMD是无法解析 !m! 的。
|
尺有所短,寸有所长,学好CMD没商量。
考虑问题复杂化,解决问题简洁化。 |
|
2006-11-4 23:07 |
|
|
willsort
元老会员
Batchinger
积分 4432
发帖 1512
注册 2002-10-18
状态 离线
|
『第
6 楼』:
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:请访问 [讨论]批处理编程的异类 ,欢迎交流与共享批处理编程心得! |
|
2007-1-20 08:32 |
|
|
electronixtar
铂金会员
积分 7493
发帖 2672
注册 2005-9-2
状态 离线
|
『第
7 楼』:
沙发,占个位置瞻仰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'>" |
|
2007-1-20 08:34 |
|
|
vkill
金牌会员
积分 4103
发帖 1744
注册 2006-1-20 来自 甘肃.临泽
状态 离线
|
『第
8 楼』:
willsort 的帖子看了受益非浅
|
|
2007-1-20 08:44 |
|
|
everest79
金牌会员
一叶枝头,万树皆春
积分 2564
发帖 1127
注册 2006-12-25
状态 离线
|
『第
9 楼』:
有好些东西,你明白,但就讲不出来,这就是工匠与大师的区别
-------小泥水匠everest79
|
|
2007-1-20 09:03 |
|