[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
返回列表 发帖

学习批处理入门篇后的一点疑问

当执行下面的命令后 echo %time% &ping 127.0.0.1 >nul &echo %time% 为什么两次显示的时间都是一样的呢
而当:echo %time%
          ping 127.0.0.1 >nul
          echo %time%
后 两次显示的时间却是 不同的?请问这是什么原因呢
               谢谢指教

测试如下代码。复制内容到剪贴板代码:
  1. @echo off
  2. set a=0b0c00a000s&echo %a%
  3. pause
复制代码
保存为bat。运行,你会发现a的值并不是你所想的那样,而是显示echo处于关闭状态。
这是因为CMD命令解释器在读到set a=0b0c00a000s&echo %a%这一条完整的语句时,发现a用%%闭合,是个变量,会把它替换成之前所赋给它的字符串常量,并把它打印出来。而在这条完整的语句之前并没有给a赋值,即是空值。所以才会显示echo处于关闭状态。请理解“一条完整的语句”的意思。
set a=0b0c00a00s&echo %a% 这才是一条完整的语句。
同样的,for语句中给a赋值,然后又在for中引用%a%,在这之前,CMD早就把它替换为空值了,所以你的代码会出错。
如何避免这种出错呢,要用到变量延迟了。
setlocal enabledelayedexpansion 这条语句的意思即是开启变量延迟。它的作用就是要告诉CMD,在读到一条完整的语句时,不要急匆匆地扩展变量。而是在执行复合语句(for语句或if语句中其后用一对圆括号闭合的所有语句称为复合语句,用&或&&连接的也是复合语句。)中的某单条语句之后,再执行变量的扩展,也就是说,这个变量扩展的行为被延后了。在开启延迟之后,在for中给变量a赋值,又在for中引用a,此时,就不应用%%将其闭合了,而是用!!。
你的代码应该是这样。复制内容到剪贴板代码:
  1. @echo off&setlocal enabledelayedexpansion
  2. echo %time%&ping 127.1 /n 5 >nul&echo !time!
  3. pause
复制代码
还要记得,如果在复合语句之外再次引用变量,此时它的值是在复合语句之内最后得到的值。
  1. @echo off&setlocal enabledelayedexpansion
  2. for /l %%a in (100 1 199) do set var=%%a&echo !var:~1!
  3. echo %var%
  4. pause
复制代码
关于变量延迟,搜索一下,多做测试很快就能明白了,我说的很粗糙。
心绪平和,眼藏静谧。

TOP

对 斑竹的讲解的理解:
当执行一个 要显示 变量 值的 命令时候 系统返还给你的是这个变量的在执行本条命令之前的值
例如说 set xcqkenl=xcqkenl00 &echo %xcqkenl% 则结果显示为%xcqkenl% 而非 xcqkenl00,(注:之前未对xcqkenl赋值)  当然当我们再次执行 set xcqkenl=xcqkenl00 &echo %xcqkenl%  显示结果为 xcqkenl00,但是我们不能误解是是第二条命令产生的 而是 我们第一次执行的命令产生的结果!
最后 总结就是说当我们执行一条命令时候 就算我们对一个变量赋值啦 但是系统依然 会给你取这个变量之前的值!

请问 斑竹 我的理解对不对
嘿嘿

TOP

回复 3楼 的帖子

只说对了一半。
例如说 set xcqkenl=xcqkenl00 &echo %xcqkenl% 则结果显示为%xcqkenl% 而非 xcqkenl00
这句,你是在CMD中这样做的吧,在CMD中显示%xcqkenl% 在批处理中会显示echo处于关闭状态。这就是CMD与批处理的区别,这就要牵扯到cmd的预处理机制了,这东西复杂得很。
关于变量延迟,请记住“即时”这个关键词。
  1. @echo off
  2. ::步骤1
  3. set xcqkenl=xcqkenl00 &echo %xcqkenl%
  4. ::步骤2
  5. set xcqkenl=xcqkenl &echo %xcqkenl%
  6. pause
复制代码
以上代码存为批处理。
步骤1会显示echo处于关闭状态,是因为这条完整的语句之前并没有给xcqkenl赋值,所以会输出这样的结果。
步骤2会显示xcqkenl00,是因为在在步骤一中给它赋的值,并不是步骤2中的值。
要得到即时得到的值。用变量延迟。
  1. @echo off&setlocal enabledelayedexpansion
  2. set a=a&echo %a%
  3. echo %a%
  4. set a=b&echo %a%
  5. set a=c&echo !a!
  6. pause
复制代码
以上,运行时,请注意每条语句的输出结果。
心绪平和,眼藏静谧。

TOP

不是特别的复杂的时候基本明白。

TOP

对头 我是 直接在cmd中运行的

TOP

斑竹说 关于变量延迟 可以理解为 就是立即 刷新 变量的值 即斑竹说的 “即时”
很有意思

TOP

我来补充两句:
一、在cmd中一样可以开启变量延迟,大家可以在cmd中依行输入如下命令,然后看结果
cmd /v:on
set "a=123"&echo !a!
二、可以用call来替代变量延迟的作用,大家可以在cmd中输入如下命令,再看结果
set "a=123"&echo %a%
set a=
set "a=456"&call,echo %a%

[ 本帖最后由 batman 于 2008-8-11 23:18 编辑 ]
***共同提高***

TOP

请问 batman 能不能讲下关于
二、可以用call来替代变量延迟的作用,大家可以在cmd中输入如下命令,再看结果
set "a=123"&echo %a%
set a=
set "a=456"&call,echo %a%

中call的运行机制呀

TOP

7楼正解

这样理解就可以了,虽然可能还是不太严谨,但我一直是这么过来的。
call的作用好多啊。调用、解析变量。
关于调用,call/?中说的已经很清楚了,可以对一个外部批处理进行调用的同时给它传递参数,也可以当前的另外一个标签进行调用,同样可以传递参数。示例:
  1. @echo off
  2. call :lp1 我是参数
  3. goto lp2
  4. :lp1
  5. echo %1
  6. goto :eof
  7. :lp2
  8. echo [%1] —— %%1在我这里不管用了。
  9. pause>nul&exit/b
复制代码
详细请参照这篇帖子: goto for call三种句式  http://bbs.bathome.net/viewthread.php?tid=1267
关于call解释变量,如下,测试两段代码。
一、
  1. @echo off
  2. :: %windir%
  3. :: Purification
  4. :: %computername%
  5. :: %username%
  6. :: %random% %random%
  7. :: %time%
  8. for /f "delims=" %%a in (%~fs0) do echo %%a
  9. pause
复制代码
二、
  1. @echo off
  2. :: %windir%
  3. :: Purification
  4. :: %computername%
  5. :: %username%
  6. :: %random% %random%
  7. :: %time%
  8. for /f "delims=" %%a in (%~fs0) do call echo %%a
  9. pause
复制代码

请先注意两段代码的区别。。第二个只不过比第一个多了一个call,运行,分别看下两段代码的输出结果。希望你能从中总结出什么道道。

[ 本帖最后由 pusofalse 于 2008-8-12 09:55 编辑 ]
心绪平和,眼藏静谧。

TOP

无法总结

Pusofalse兄:你的这两段代码,我测试及思考了很久。
但没有总结到什么,甚至越看越糊涂。都不知道他到底为什么会显示这样的结果了。
你能帮忙解释一下吗?谢了

TOP

很有意义的一个帖子,值得学习

TOP

回复 11楼 的帖子

一个没具体值是变量名一个是具体值

TOP

不同变量所对应的同来的结果会不同。

TOP

原帖由 CZT 于 2008-9-2 12:51 发表
Pusofalse兄:你的这两段代码,我测试及思考了很久。
但没有总结到什么,甚至越看越糊涂。都不知道他到底为什么会显示这样的结果了。
你能帮忙解释一下吗?谢了

echo %time%
ping 127.0.0.1 >nul
echo %time%
两次的显示不同,是因为%time%是一个动态环境变量。

echo %time% &ping 127.0.0.1 >nul &echo %time%

如果不是特殊原因,这样写本身是错误的,因为后一个变量%time%没有被动态扩展,具体参考“变量延迟”和“预处理机制”的相关论坛贴。他的正确写法(批处理中)为:
setlocal enabledelayedexpansion
echo %time% &ping 127.0.0.1 >nul &echo !time!
寒夜孤星:在没有说明的情况下,本人所有代码均运行在 XP SP3 下 (有问题请发贴,QQ临时会话已关闭)

TOP

返回列表