|
yuanzijia08
初级用户
 
积分 78
发帖 30
注册 2006-6-17 来自 湖南湘潭
状态 离线
|
『楼 主』:
SOS!!!!!!请教关于变量延迟!!
使用 LLM 解释/回答一下
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 ]
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
This is a batch script written by brother kcdsw. He himself said there are the following problems:
If you use set and then echo, then the % in the text will be replaced.
If you use call without enabling variable delay, when passing %%m from for to call, things will also be lost.
So I still enabled variable delay, and the result is that the! are all gone. I hope experts can give advice.
I want to put aside these problems for now.
I want to ask experts to explain according to this example how variable delay works and why it is delayed.
From the sentence above "If you use call without enabling variable delay, when passing %%m from for to call, things will also be lost", I guess it is because parameters cannot be passed between the two segments, and variable delay is used. I have checked a lot on the Internet and still don't fully understand variable delay, so I hope experts will focus on explaining.
Last edited by yuanzijia08 on 2006-11-4 at 02:31 PM ]
|
|
2006-11-4 14:30 |
|
|
yuanzijia08
初级用户
 
积分 78
发帖 30
注册 2006-6-17 来自 湖南湘潭
状态 离线
|
『第 2 楼』:
使用 LLM 解释/回答一下
@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 想请高手依据这两个例子来说说 启用了变量延迟和 关闭变量延迟有什么不同
万分感谢!!!!
```batch
@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
```
This is a version rewritten by an elder to help kcdsw solve the problem. It turns off variable delay and uses call. I want to ask experts to talk about the differences between enabling variable delay and turning off variable delay based on these two examples.
Thanks a lot!!!!!
|
|
2006-11-4 14:35 |
|
|
namejm
荣誉版主
       batch fan
积分 5226
发帖 1737
注册 2006-3-10 来自 成都
状态 离线
|
|
2006-11-4 16:16 |
|
|
yuanzijia08
初级用户
 
积分 78
发帖 30
注册 2006-6-17 来自 湖南湘潭
状态 离线
|
『第 4 楼』:
使用 LLM 解释/回答一下
精华版的教程绝对不适合初学者 我是看了好多遍才来问的 我个人觉得还是要以一个事例来分析更好
我先假设程序实在这样的:(比原程序少了个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! 用其值替换掉 这有什么不对? 为什么还要开启变量延迟呢?
开启了变量延迟 这个程序又是怎么一步一步执行的?
The essence version of the tutorial is definitely not suitable for beginners. I asked after reading it many times. Personally, I think it's better to analyze it with an example.
I first assume the program is like this: (missing a setlocal EnableDelayedExpansion, that is, not enabling variable delay)
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
There are these sentences in the essence version:
The behavior of the command interpreter expanding environment variables is roughly as follows: First, read a complete statement of the command line. After some preliminary preprocessing, before the command is interpreted and executed, it will match the strings closed by percent signs in it. If a matching environment variable is found in the environment space, its value will replace the original string and the percent sign itself. If no match is obtained, an empty string will replace it. This process is the "expansion" of the environment variable, which still belongs to the preliminary preprocessing category of the command line.
After some preliminary preprocessing, before the command is interpreted and executed, it will match the strings closed by percent signs in it
Doesn't this mean that before the execution of the statement 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
)
it will match the strings closed by percent signs? Then it's okay! When the for statement reads the first line of ('findstr /v /C:"730 730" cover.ps') this data, m=0, then m=1, 2, 3....... As long as before the execution of if !m! == 686 (pause) else (echo %%m >>cover3.txt), replace!m! with its value. What's wrong with this? Why do we still need to enable variable delay?
How does this program execute step by step after enabling variable delay?
|
|
2006-11-4 22:47 |
|
|
namejm
荣誉版主
       batch fan
积分 5226
发帖 1737
注册 2006-3-10 来自 成都
状态 离线
|
『第 5 楼』:
使用 LLM 解释/回答一下
既然用了 !m! 的格式,也就意味着开启了变量的延迟功能,所以,setlocal EnableDelayedExpansion 语句绝对不能少,否则,CMD是无法解析 !m! 的。
Since the !m! format is used, it means that the delayed expansion function of variables is enabled. Therefore, the setlocal EnableDelayedExpansion statement must not be missing; otherwise, CMD cannot parse !m!.
|

尺有所短,寸有所长,学好CMD没商量。
考虑问题复杂化,解决问题简洁化。 |
|
2006-11-4 23:07 |
|
|
willsort
元老会员
         Batchinger
积分 4432
发帖 1512
注册 2002-10-18
状态 离线
|
『第 6 楼』:
使用 LLM 解释/回答一下
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 ]
Re: yuanzijia08:
From the above discussion, brother indeed has carried out a more in-depth thinking on "variable delayed expansion".
The misunderstanding of brother is that he has not thoroughly understood the concept of "complete statement" mentioned in my original document.
That is to say, for cmd that interprets and executes batch processing, the following code is just "one" statement, which we can call a "compound statement". Of course, Microsoft official does not call it like this.
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
)
And before this statement is interpreted and executed, all % are escaped and replaced, including %%m which is also replaced into %m. And if there is %m% in it, it will directly replace into a relatively fixed "constant", and it will no longer be a variable; that is to say, no matter what changes are made to variable m inside for, it can only be perceived after the for statement is executed. Inside for, %m% has no longer changed.
But the actual situation is that we often need to perceive a variable dynamically changing in for statement, because we need to use these changes to complete some application implementations. So, cmd introduced the mechanism of delayed expansion and special escape symbol !.
At this time, cmd still follows the above-mentioned mechanism for the processing of %, but it performs another way of parsing the variables enclosed by !! which were not processed originally. When cmd analyzes the for statement, it still reads in the "whole sentence", preprocesses, expands variables, etc., and then starts the processing flow inside the for statement, which is equivalent to using a streamlined cmd loop to execute another batch processing. In this process, the !! string that is not processed outside for will be expanded in a similar way to %% variables, and this expansion process is similar to interpreting an ordinary batch processing file.
In short, before enabling delay, all variables in the code are already replaced before the code in () is executed; and after enabling delay, the replacement work is delayed until before each statement in () is executed.
The same working mechanism exists in if/else compound statements, any compound statements enclosed by () and compound statements connected by |, &, &&, ||.
In addition, it needs to be explained that variables in cmd also have the distinction between global and local, but this distinction is not divided by () which is similar to the statement block in C language. For example, if we define a variable in the for statement, then after the for is executed, this variable still exists. This has no substantial connection with the variable delayed expansion we are discussing.
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 楼』:
使用 LLM 解释/回答一下
沙发,占个位置瞻仰willsort的帖子
Last edited by electronixtar on 2007-1-20 at 08:41 AM ]
Sofa, occupy a position to worship the post of 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 楼』:
使用 LLM 解释/回答一下
willsort 的帖子看了受益非浅
I've benefited a lot from willsort's post
|
|
2007-1-20 08:44 |
|
|
everest79
金牌会员
      一叶枝头,万树皆春
积分 2564
发帖 1127
注册 2006-12-25
状态 离线
|
『第 9 楼』:
使用 LLM 解释/回答一下
有好些东西,你明白,但就讲不出来,这就是工匠与大师的区别
-------小泥水匠everest79
There are many things that you understand but just can't put into words. This is the difference between a craftsman and a master.
-------Little Bricklayer everest79
|
|
2007-1-20 09:03 |
|