标题: 不用变量延迟[setlocal enableDelayedExpansion]也可以计算
[打印本页]
作者: wxcute
时间: 2008-6-24 22:20
标题: 不用变量延迟[setlocal enableDelayedExpansion]也可以计算
可能大家都知道,供还不知道的人学习下吧。
也可以用在其他地方。
::不用变量延迟[setlocal enableDelayedExpansion]也可以计算
@echo off
for /f %%a in ('dir/b') do call :num_add file_num
echo 目录下有%file_num%个文件(夹)。
pause
goto :eof
:num_add
set/a %1+=1
goto :eof
作者: HAT
时间: 2008-6-24 22:36
不知道,学习。
作者: lxmxn
时间: 2008-6-24 22:55
Quote: |
Originally posted by HAT at 2008-6-24 22:36:
不知道,学习。 |
|
Orz ……
作者: PPdos
时间: 2008-6-24 22:56
这也是call的作用所在
(for /f %i in ('dir /b') do set /a n+=1 >nul)&call echo 目录下有%n%个文件(夹)
作者: wxcute
时间: 2008-6-25 18:59
4楼的又是我见的一种新用法。
作者: PPdos
时间: 2008-6-25 19:03
这跟楼主的没有什么区别 只是简化了一下
作者: wxcute
时间: 2008-6-25 19:07
不过我是新手,对这样的用法觉得有点奇怪,也不是很习惯。
还是要多与各位学习阿。
作者: radem
时间: 2008-6-25 19:07
我也要学。
作者: metoo
时间: 2008-6-25 19:22
这种都不能代替延迟变量。都是在完全结束一个for+set循环后显示最终效果,根本不能使用中间环节,而延迟变量的作用就是使用set的中间结果
@echo off
for /f %%a in ('dir/b') do (
call :num_add file_num
echo %file_num%
)
echo 目录下有%file_num%个文件(夹)。
pause
goto :eof
:num_add
set/a %1+=1
goto :eof
@echo off
for /f %%i in ('dir /b') do (
set /a n+=1 >nul
echo %n%
)
echo 目录下有%n%个文件(夹)
pause
上边两个和楼主和上面ppdos的代码效果是一样的不能使用中间结果
@echo off
setlocal enabledelayedexpansion
for /f %%i in ('dir /b') do (
set /a n+=1 >nul
echo !n!
)
echo %n%
pause
可以比较一下结果
[
Last edited by metoo on 2008-6-25 at 07:26 PM ]
作者: PPdos
时间: 2008-6-25 19:51
如果想用中间的结果 也是可以的
(for /f "tokens=*" %i in ('dir /b') do set /a n+=1 >nul&call set _%n%=%i >nul)&call echo 目录下有%n%个文件(夹)
echo %_9%
[
Last edited by PPdos on 2008-6-25 at 01:01 PM ]
作者: metoo
时间: 2008-6-25 20:40
这个是一个取巧的办法了,是用连续多变量分别赋值达到获得其中某个中间变量的值,而不是真正的连续赋值/中间环节直接获取。是定义了n个变量来把整个for循环分步化,而这些分布结果是必须在整个循环结束后才能使用的。
[
Last edited by metoo on 2008-6-25 at 08:42 PM ]
作者: PPdos
时间: 2008-6-25 20:49
Quote: |
Originally posted by metoo at 2008-6-25 01:40 PM:
这个是一个取巧的办法了,是用连续多变量分别赋值达到获得其中某个中间变量的值,而不是真正的连续赋值/中间环节直接获取。是定义了n个变量来 ... |
|
大侠能否举个例子?
作者: qzwqzw
时间: 2008-6-25 21:09
大家说了半天
都没觉得是在围着一个很不典型的例子在讨论问题吗?
难道没人知道set /a是缺省具有延迟效果的吗?
楼主的那个例子完全用不着变量延迟或者“中间结果”云云
@echo off
for /f %%a in ('dir/b') do set /a file_num+=1
echo 目录%cd%下有%file_num%个文件(夹)。
作者: metoo
时间: 2008-6-25 21:12
- - 菜鸟而已
你的办法是想通过“变变量”的方式来获得各个步骤的,是一次性的生成n个不同的变量,这些变量需要在for命令完全执行完以后才能使用,这就是我说的取巧,而延迟变量是在for命令执行过程中就可以使用。。
@echo off
for /f "tokens=*" %%i in ('dir /b') do (
set /a n+=1 >nul
call set _%n%=%%i >nul
rem 这句其实是有问题的在for未执行完之前%n%为空,所以都是在设置 _ 这个变量的值
echo %n%
echo %_%
echo %_1%
rem 上面这3句是来验证下循环中的变量是不是能使用(我自己加出来的)
)
echo\
echo\
echo\
::换行
::到这儿整个循环结束 %n% %_% 这两个个变量生效
echo %_%
echo %n%
echo %_1%
::验证到%_1%变量不存在
echo\
echo\
echo\
::换行
::上面这3句是来验证下循环中的变量是不是能使用(我自己加出来的)
call echo 目录下有%n%个文件(夹)
pause
[
Last edited by metoo on 2008-6-25 at 09:14 PM ]
作者: qzwqzw
时间: 2008-6-25 21:15
metoo老兄9楼的言论有欠思量啊
在没有变量延迟的dos时代
也是可以“连续赋值/中间环节直接获取”的
这只需要对被call的:num_add一节做些小小的改动就可以了
而使用for+call代替for+延迟的方案
通常都会把所有的循环体代码移植到被call的子程序中
而在子程序内部是可以想怎么用就怎么用
没有什么限制的
作者: PPdos
时间: 2008-6-25 21:15
Quote: |
Originally posted by qzwqzw at 2008-6-25 02:09 PM:
大家说了半天
都没觉得是在围着一个很不典型的例子在讨论问题吗?
难道没人知道set /a是缺省具有延迟效果的吗?
楼主的那个例子完全用不着变 ... |
|
如果缩成一行写呢?
作者: qzwqzw
时间: 2008-6-25 21:20
很无味的想法
代码追求简洁明快
而非简短古怪
作者: metoo
时间: 2008-6-25 21:20
Quote: |
Originally posted by qzwqzw at 2008-6-25 09:09 PM:
大家说了半天
都没觉得是在围着一个很不典型的例子在讨论问题吗?
难道没人知道set /a是缺省具有延迟效果的吗?
楼主的那个例子完全用不着变 ... |
|
兄貌似对什么叫延迟变量了解不够透彻,同样是for循环结束后变量自然是生效的
应用上面的一个例子不用set/a
@echo off
for /f %%a in ('dir/b') do (
set ww=%%a
)
echo %ww%
pause
可以看到最后变量%ww%是会被赋予最后的值的
作者: PPdos
时间: 2008-6-25 21:30
那无奈何老大的签名岂不是让你说的一文不值拉。。。。
[
Last edited by PPdos on 2008-6-25 at 02:32 PM ]
作者: metoo
时间: 2008-6-25 21:30
Quote: |
Originally posted by qzwqzw at 2008-6-25 09:15 PM:
metoo老兄9楼的言论有欠思量啊
在没有变量延迟的dos时代
也是可以“连续赋值/中间环节直接获取”的
这只需要对被call的:num_add一节做些小小的改 ... |
|
确实。。是可以用这个格式。。
某些代码我也欠考虑了,很高兴这论坛能有这样的气氛^ ^
作者: qzwqzw
时间: 2008-6-25 21:31
metoo老兄可能是引用错了吧
我是在15楼反驳你的言论的
13楼的说法我是在证明楼主代码的多余
貌似没有什么问题
首先变量延迟我是了解的
“延迟变量”倒是第一次看见
兄在18楼的例子想说明什么问题?
任何变量在被“连续赋值”后自然都应该是最后的生效啊?
这没有什么值得讨论的啊
[
Last edited by qzwqzw on 2008-6-25 at 11:11 PM ]
作者: qzwqzw
时间: 2008-6-25 21:45
无奈何的签名其里重于其表
其中透出的无奈与豁达
我是很欣赏的
如果没有点睛的那几句释名辞
我只会视作过眼云烟
可很多人都被那古怪的结构
和willsort的一篇释义帖
搞得在技术的迷宫里迷失了方向
反而失去了最应该值得珍视的内在
不要觉得在讨论技术的地方
就应该钻技术的牛角尖
毕竟技术的讨论和发展是不断推陈出新的
而心灵的感觉和人生的体验却往往是弥足珍贵的
作者: metoo
时间: 2008-6-25 21:54
其实楼主的言论是对的- -!
然后ppdos兄的简化其实是错误的,并不能代替延迟变量,而是简单的连续赋值后的最后产物,然后我就他那个作了些解释 - -!
其实
变量延迟/延迟变量 不管叫啥吧(当然99%是我叫错了。。死鸭子也得嘴硬一下)
他存在的目的就是得到for循环内的set获得的变量变化的各个步骤然后加以处理,
当在for 应用中使用set的话是必须 变量延迟/延迟变量 的 而用call是将set至于循环命令的外圈执行,是一个不断调用子过程来达到类似 变量延迟/延迟变量 的效果
还有 无奈何的 那个签名并不是 连续赋值 注意 set/p 这个参数是个交互命令,这个地方可能是这个签名最精髓的地方
[
Last edited by metoo on 2008-6-25 at 09:56 PM ]
作者: PPdos
时间: 2008-6-25 21:58
大家都没说楼主说的错啊~~?
我只是觉得楼主 写的长了点给简化一下
是否错误 那还是仁者见仁
作者: wxcute
时间: 2008-6-25 22:16
没想到这么多人讨论。
就像第1页15楼qzwqzw说的,改成这样就能显示中间的了。
还有metoo也挺搞笑“嘴硬的死鸭子”
@echo off
for /f %%a in ('dir/b') do call :num_add file_num
echo 目录下有%file_num%个文件(夹)。
pause
goto :eof
:num_add
set/a %1+=1
::加了下一行
echo %file_num%
goto :eof
[
Last edited by wxcute on 2008-6-25 at 10:25 PM ]
作者: qzwqzw
时间: 2008-6-25 22:21
首先,楼主的言论肯定是对的
计算当然可以不用变量延迟(即使是在for中计算)
当然,这里的“计算”说得很模糊
导致各人有各人的理解
楼主这里的潜台词是可以用call来代替延迟
因为他的代码中出现了call
其次,楼主的代码也是没有问题的
语法正确无误且能达到想要的效果
我想表明的是
楼主的代码证明不了楼主观点中的潜台词
因为我用非call且非延迟的方式也能实现同样的目的
那就无法结实call可以代替延迟的意义
--------------------------------------------------------
从ppdos的第一回帖来看
是了解我在14楼提到的set /a的缺省延迟效果的
只不过没把它当成一个问题与楼主的言论联系起来而已
简化本身没有问题
我也只是认为缩成一行代码略显多余
也能从中找到证明call能代替延迟的观点的佐证
(for /f %i in ('dir /b') do set /a n+=1 >nul)&call echo 目录下有%n%个文件(夹)
可以代替
(for /f %i in ('dir /b') do set /a n+=1 >nul)&echo 目录下有!n!个文件(夹)
这说明连接语句中遇到变量延迟问题可以用call替换
而metoo却往for里面去看
当然是看不到什么有价值的东西的
--------------------------------------------------------
至于无奈何的签名
那真是又扯远了
我现在只记得那几句词
代码早忘得个干净
也不耐再去翻腾出来
且管它是不是连续赋值
[
Last edited by qzwqzw on 2008-6-25 at 10:28 PM ]
作者: metoo
时间: 2008-6-25 22:27
作者的方法是对的。。但是那个简化版的是作不到代替延迟变量的。。这点错误我已经意识到了。。话说无奈何斑竹那个是特殊情况,不是连续赋予值。。用的set/p的交互方式。。。那个call也不是这种用法。。仿冒他的签名写了个p版的
@echo off
set tt=一二三四五,上山打老虎,老虎不在家,回家吃番薯。 ——metoo冒牌版
for /l %%i in (0,1,36)do (
call call set/p= %%%%tt:~%%i,1%%%%<nul&ping/n 1 127.1>nul
)
按照楼上说法那我这个call call 是何种解释呢?
[
Last edited by metoo on 2008-6-25 at 10:40 PM ]
作者: wxcute
时间: 2008-6-25 22:30
其实我也菜鸟一个,没想得那么深。
只是习惯了用%,要用!代替%有点不适应,还有就是写“setlocal enableDelayedExpansion”挺费事的。我记性不好,记了有段时间才记住。
作者: metoo
时间: 2008-6-25 22:33
Quote: |
Originally posted by wxcute at 2008-6-25 10:30 PM:
其实我也菜鸟一个,没想得那么深。
只是习惯了用%,要用!代替%有点不适应,还有就是写“setlocal enableDelayedExpansion”挺费事的。我记性不好,记了有段时间才记住。 |
|

鄙人也是菜鸟一个,话说其实这东西我现在都记不住。。我在editplus里设置了一个快捷输入!
作者: qzwqzw
时间: 2008-6-25 22:38
人一多就显得有些乱了
再加上有几位喜欢编辑帖子的
看着看着就觉得思路连不上了
现在理顺一下
ppdos开始只是想简化楼主的代码
后来提出无奈何签名是反驳我“简短古怪不可取”的言论
metoo是想说明变量延迟的“连续赋值”意义并以此证明其不可替代
后来提到无奈何的签名没有用变量延迟是因为没有用“连续赋值”
我刚开始只是想说楼主的代码证明不了楼主的观点
现在我想延伸楼主的观点——
for+call可以替代for+延迟,无论何种情况下
欢迎大家举出例子反驳我的观点
顺便也是对自己编程思想和代码技巧的一次整理
作者: qzwqzw
时间: 2008-6-25 22:39
啥都不说了,知音难觅啊
作者: quya
时间: 2008-6-25 22:42
几次看见 ping/n 1 127.1, 我知道这个命令的本来意思,但用在类似于这样的代码起到了什么作用,能否给我这个土鸟解释下。
谢谢!
作者: metoo
时间: 2008-6-25 22:43
Quote: |
Originally posted by qzwqzw at 2008-6-25 10:38 PM:
人一多就显得有些乱了
再加上有几位喜欢编辑帖子的
看着看着就觉得思路连不上了
现在理顺一下
ppdos开始只是想简化楼主的代码
后来提出无奈 ... |
|
鄙人的开始观点已经意识到错误了,基本统一楼上观点,
但是我认为ppdos的简写方式是不对的
作者: metoo
时间: 2008-6-25 22:44
Quote: |
Originally posted by qzwqzw at 2008-6-25 10:39 PM:
啥都不说了,知音难觅啊 |
|

哈哈,知音难觅,居然还有同好的
作者: metoo
时间: 2008-6-25 22:47
Quote: |
Originally posted by quya at 2008-6-25 10:42 PM:
几次看见 ping/n 1 127.1, 我知道这个命令的本来意思,但用在类似于这样的代码起到了什么作用,能否给我这个土鸟解释下。
谢谢! |
|
搜索论坛关于批处理运行时间延迟方面的帖子
作者: PPdos
时间: 2008-6-25 22:51
关于缩成一行的代码 个人而言
是为了能更方便的在dos命令行中直接测试
个人觉得很有必要 测试程序并非多余
(只是我手懒 能一行写出来的都不想建个批文件)
作者: HAT
时间: 2008-6-25 22:51
Quote: |
Originally posted by quya at 2008-6-25 10:42 PM:
几次看见 ping/n 1 127.1, 我知道这个命令的本来意思,但用在类似于这样的代码起到了什么作用,能否给我这个土鸟解释下。
谢谢! |
|
仔细阅读这个帖子
http://www.cn-dos.net/forum/viewthread.php?tid=8905#pid54227
作者: wxcute
时间: 2008-6-25 23:19
刚才居然中毒了,不知道是哪个可恶的家伙。很郁闷阿。
另editplus好用吗?原来有这样的好东东。用notepad习惯了,可是累阿,要改改。下载个先。
作者: quya
时间: 2008-6-26 10:11
Quote: |
Originally posted by wxcute at 2008-6-25 11:19 PM:
刚才居然中毒了,不知道是哪个可恶的家伙。很郁闷阿。
另editplus好用吗?原来有这样的好东东。用notepad习惯了,可是累阿,要改改。下载个先。 |
|
大家以后中毒并且杀毒软件杀不了的话,可以找我。
我老土批处理虽然不行,可是手工杀毒的本事那是天下无双啊。
作者: zh159
时间: 2008-6-26 10:35
缩成一行在命令行中直接测试而不显示set/a部分:
echo off&(for /f %i in ('dir /b') do set /a n+=1 >nul)&call echo 目录下有%n%个文件(夹)&echo on
作者: hjkk123
时间: 2008-6-26 10:55
学习了
作者: qzwqzw
时间: 2008-6-26 13:58
看来大家都缺乏彻底的实践精神啊!
讨论了这半天
只有经过了测试才发现ppdos以及zh159精简代码的大问题
因为他们所有的代码都经不起多次运行的考验
第一次运行结果都是对的
比如是7
但第二次运行结果却出错
本来应该是14,结果却仍然是7
第三次仍然错了,本来是21,结果却是14
也就是说在没有设置setlocal的变量环境下
环境变量是会随着运行次数递增的
但是call echo出来的却总是for执行之前的结果
除非call echo的变量此句代码运行前是空
最后的到的结论是
在连接语句中是无法完全用 call echo %var% 代替 echo !var! 的
所以我在26楼中间那段中所表明的最后论点是错的
当然这并不影响我在30楼提到的观点
for+call是可以完全替代for+延迟
至于40楼的代码除了以上提到的共性问题外
思路上也绕了弯子
想不显示set /a只需要一个@标记就可以了
用不着祭起echo off这把牛刀
(for /f %i in ('dir /b') do @set /a n+=1 >nul)&call echo 目录下有%n%
但是我仍然申明
这种缩写很没有意思
先执行for再执行echo %n%
既简单又清晰
还不会出现我所说的上述问题
何苦来哉!
作者: metoo
时间: 2008-6-26 15:21
Quote: |
Originally posted by qzwqzw at 2008-6-26 01:58 PM:
看来大家都缺乏彻底的实践精神啊!
讨论了这半天
只有经过了测试才发现ppdos以及zh159精简代码的大问题
因为他们所有的代码都经不起多次运行的 ... |
|
对头,精简代码是错误的,仅仅相当于一个for完成后再echo一下
而楼主的代码确实可以带替延迟变量
可以看下我的27楼回复的代码,那个call和楼主的 call完全是两种不同的用法
作者: zh159
时间: 2008-6-26 16:17
确实忘了在set/a前使用@
1、在命令行里使用,如果你不清空变量,下次的结果肯定会递增,这你不会不知道!
2、在命令行里使用,如果单纯的for后再来一个echo,那是两次输入命令(先输入一次for回车后再输入echo)。
PS:能不用call
跳转最好不要用,对效率有一定的影响
作者: plp626
时间: 2008-6-26 18:53
就一个变量延迟的讨论,竟然这么激烈,我是感觉楼主的代码没什么新鲜之处,我写"子过程"时常用到的.
不过我说个题外话, 楼主举的这个例子不必用for又用set(我喜欢在命令行下用批处理,喜欢信手拈来的感觉)
::文件数
dir/a-d/b|find /c /v ""
::目录数
dir/ad/b|find /c /v ""
::文件与目录数
dir/a-d|findstr/bc:" "
作者: knoppix7
时间: 2008-6-26 19:18
call echo %var% ?
我怎么感觉如果
call echo %%var%%
Call一次加一对%
貌似..
作者: quya
时间: 2008-6-26 19:43
45楼的代码真的是简洁明快。
作者: PPdos
时间: 2008-6-27 02:16
Quote: |
但是我仍然申明
这种缩写很没有意思
先执行for再执行echo %n%
既简单又清晰
还不会出现我所说的上述问题 |
|
一行代码和几行代码 各有其优缺点
磨灭任何一方的作用都是不妥的
之所以缩成一行写 无非是想利用上call
从而说明 call一定程度上代替了 setlocal enabledelayedexpansion的作用
是否能够100%的代替? 不置可否!
作者: wxcute
时间: 2008-6-27 13:05
Quote: |
Originally posted by plp626 at 2008-6-26 18:53:
就一个变量延迟的讨论,竟然这么激烈,我是感觉楼主的代码没什么新鲜之处,我写"子过程"时常用到的.
不过我说个题外话, 楼主举的这个例子不 ... |
|
其实就是因为想到你说的“子过程”,我才帖了个。这样除了这个地方,在其他要递加的地方也可以用到了。
还有就是我还有很多命令不熟悉,像find、findstr等。所以一些本可以简单的代码也写复杂了。
作者: asnahu
时间: 2009-8-7 04:15
标题: 10楼代码有误
Quote: |
Originally posted by PPdos at 2008-6-25 19:51:
如果想用中间的结果 也是可以的
[code](for /f "tokens=*" %i in ('dir /b') do set /a n+=1 >nul&call set _%n%=%i >nul)&call echo 目录下有%n%个文件(夹)[/ ... |
|
将代码复制粘贴到命令提示符,然后多运行几次,即可看到,数字一直在增加,与实际文本(夹)数量不符。
[
Last edited by asnahu on 2009-8-7 at 04:20 ]