Board logo

标题: [已解決]批处理中call和set怎样合用? [打印本页]

作者: strong12345    时间: 2009-2-12 12:24     标题: [已解決]批处理中call和set怎样合用?

小弟在之前發的一文中
版主大大們幫我解決了問題,並提供代碼
小弟在之前发的一文中
版主大大们帮我解决了问题,并提供代码
小弟常感谢

不过里面有句 call 和 set 合用的问题
想请教一下

因为小弟觉得这跟原本小弟问的问题性质不太相同,所以另外开了此帖发问

原代码:
  1. @echo off
  2. for /f "delims=" %%a in ('dir/b') do call set dir_list=%%dir_list%% %%a
  3. echo %dir_list%
  4. pause
复制代码
其中
  1. for /f "delims=" %%a in ('dir/b') do call set dir_list=%%dir_list%% %%a
复制代码
小弟并不是很理解
为什么可以这样使用指令?

set dir_list=%%dir_list%%  →为什么使用 %% 而不是 % ?
后面的 %%a 应该是 %1 的意思吧?
请问为什么这么做 可以把 %%a 的变数,一直加到 %dir_list%里?

小弟知道 set 和 call 的用法
不过2个 合在一起 这样使用 实在不太懂   @@a"
能不能请哪位大大
说明一下 这指令的流程?

[ 本帖最后由 strong12345 于 2009-2-13 20:29 编辑 ]
作者: Batcher    时间: 2009-2-12 12:35

参考《for语句从入门到精通》中关于变量延迟扩展的讲解
http://bbs.bathome.net/thread-2189-1-1.html
作者: batman    时间: 2009-2-12 23:14

这就是call的延迟用法,楼主可比较下下面两段代码:
  1. @echo off
  2. set "a=1"
  3. set "a=2"&echo %a%
  4. pause>nul
复制代码
  1. @echo off
  2. set "a=1"
  3. set "a=2"&call,echo %%a%%
  4. pause>nul
复制代码
第一段代码显示出1,也就是第二次赋值没有成功,而第二段代码显示出2,显然第二次赋值被确认。这其实也涉及到cmd的预处理
机制,cmd会按由上至下的顺序(有跳转除外)逐行读取和处理程序命令(注意在一个括号内的命令也被视为一行),在上面第一
个代码中set "a=2"&....是被做为一条命令读取的,读取后cmd就会分析变量a在前面是否已被定义,如有就延缓前面的定义,所以显
示为1(前面变量a被定义为1)。而在第二个代码中因为有了call的延迟作用,cmd将会将set "a=2"&这一行两做为两个命令来执行,
所以变量a被定义为2,但记住加入了call后变量符号要由原来的%%改为%%%%。将第一个代码做如下修改也可达到同样效果(开启
变量延迟):
  1. @echo off&setlocal enabledelayedexpansion
  2. set "a=1"
  3. set "a=2"&echo !a!
  4. pause>nul
复制代码

[ 本帖最后由 batman 于 2009-2-12 23:15 编辑 ]
作者: namejm    时间: 2009-2-12 23:21

  “逐行读取”的提法之后,应该再加上“逐条执行”的说法,否则,很容易被顺理成章地误解为逐行执行的,对新手而言,“逐条执行”的概念需要扎根心底,才能更好地理解变量延迟的运作机制。
作者: batman    时间: 2009-2-13 00:28

多谢namejm的指正,确实是如此,是本人未考虑周全了。。。
作者: strong12345    时间: 2009-2-13 18:36

版主大大
小弟改成这样
  1. @echo off
  2. for /f %%a in ('dir /b') do (call set dir_list=%%dir_list%% %%a)
  3. set dir_list
  4. pause
复制代码
也能显示所有档案
但是小弟不懂为什么
  1. call set dir_list=%%dir_list%% %%a
复制代码
把变数dir_list设为自己  后面又接了一个 %%a ??

小弟目前知道的是∶
dir /b 指令输出  会变成%%a
不知道为什么%%a 又变成 %dir_list%

延迟变量部份已经懂了 谢谢

[ 本帖最后由 strong12345 于 2009-2-13 18:48 编辑 ]
作者: strong12345    时间: 2009-2-13 20:27

小弟刚刚吃饭时,自己想想
终于想通了
刚刚做了个实验
  1. @echo off
  2. for /f %%a in ('dir /b') do (call set dir_list=%%dir_list%% %%a&set dir_list&pause)
  3. pause
复制代码

证实我想的没错

问题已解 ^_^
作者: LWJ菜鸟    时间: 2011-6-27 16:20

这就是call的延迟用法,楼主可比较下下面两段代码:@echo off
set "a=1"
set "a=2"&echo %a%
pause>nul@echo off
set "a=1"
set "a=2"&call,echo %%a%%
pause>nul第一段代码显示出1,也就是第二次赋值没有成功 ...
batman 发表于 2009-2-12 23:14

请问bathman:
按照你的说明,如果有setlocal enabledelayedexpansion就不用CALL来进行延迟,但是为什么下面这段代码缺少了其中任何一个就不行啊?
  1. @echo off&setlocal enabledelayedexpansion
  2. set "str=abcdefghijklmnopqrstuvwxyz0123456789"
  3. set "code=jpg txt bat exe wma mp3"
  4. md test&cd test
  5. for /l %%a in (1,1,20) do (
  6.     for /l %%b in (1,1,9) do (
  7.           set /a a=!random!%%36
  8.           call,set "var=!var!%%str:~!a!,1%%"
  9.      )
  10.     set /a b=!random!%%6+1&call :lp
  11.     set "var="
  12. )
  13. goto :eof
  14. :lp
  15. for /f "tokens=%b%" %%c in ("%code%") do echo.>!var!.%%c
复制代码

作者: 我是马甲    时间: 2011-6-27 16:54

8# LWJ菜鸟

参考 http://bbs.bathome.net/viewthrea ... hlight=%D0%A7%C2%CA




欢迎光临 批处理之家 (http://www.bathome.net/) Powered by Discuz! 7.2