中国DOS联盟论坛

中国DOS联盟

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

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

游客:  注册 | 登录 | 命令行 | 会员 | 搜索 | 上传 | 帮助 »
中国DOS联盟论坛 » DOS批处理 & 脚本技术(批处理室) » SOS!!!!!!请教关于变量延迟!!
作者:
标题: SOS!!!!!!请教关于变量延迟!! 上一主题 | 下一主题
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
查看资料  发短消息 网志   编辑帖子  回复  引用回复

请注意:您目前尚未注册或登录,请您注册登录以使用论坛的各项功能,例如发表和回复帖子等。


可打印版本 | 推荐给朋友 | 订阅主题 | 收藏主题



论坛跳转: