标题: 学习批处理入门篇后的一点疑问 [打印本页]
作者: xcqkenl 时间: 2008-8-11 17:16 标题: 学习批处理入门篇后的一点疑问
当执行下面的命令后 echo %time% &ping 127.0.0.1 >nul &echo %time% 为什么两次显示的时间都是一样的呢
而当:echo %time%
ping 127.0.0.1 >nul
echo %time%
后 两次显示的时间却是 不同的?请问这是什么原因呢
谢谢指教
作者: pusofalse 时间: 2008-8-11 17:23
测试如下代码。复制内容到剪贴板代码:- @echo off
- set a=0b0c00a000s&echo %a%
- 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,此时,就不应用%%将其闭合了,而是用!!。
你的代码应该是这样。复制内容到剪贴板代码:- @echo off&setlocal enabledelayedexpansion
- echo %time%&ping 127.1 /n 5 >nul&echo !time!
- pause
复制代码
还要记得,如果在复合语句之外再次引用变量,此时它的值是在复合语句之内最后得到的值。- @echo off&setlocal enabledelayedexpansion
- for /l %%a in (100 1 199) do set var=%%a&echo !var:~1!
- echo %var%
- pause
复制代码
关于变量延迟,搜索一下,多做测试很快就能明白了,我说的很粗糙。
作者: xcqkenl 时间: 2008-8-11 17:48
对 斑竹的讲解的理解:
当执行一个 要显示 变量 值的 命令时候 系统返还给你的是这个变量的在执行本条命令之前的值
例如说 set xcqkenl=xcqkenl00 &echo %xcqkenl% 则结果显示为%xcqkenl% 而非 xcqkenl00,(注:之前未对xcqkenl赋值) 当然当我们再次执行 set xcqkenl=xcqkenl00 &echo %xcqkenl% 显示结果为 xcqkenl00,但是我们不能误解是是第二条命令产生的 而是 我们第一次执行的命令产生的结果!
最后 总结就是说当我们执行一条命令时候 就算我们对一个变量赋值啦 但是系统依然 会给你取这个变量之前的值!
请问 斑竹 我的理解对不对
嘿嘿
作者: pusofalse 时间: 2008-8-11 18:28 标题: 回复 3楼 的帖子
只说对了一半。
例如说 set xcqkenl=xcqkenl00 &echo %xcqkenl% 则结果显示为%xcqkenl% 而非 xcqkenl00
这句,你是在CMD中这样做的吧,在CMD中显示%xcqkenl% 在批处理中会显示echo处于关闭状态。这就是CMD与批处理的区别,这就要牵扯到cmd的预处理机制了,这东西复杂得很。
关于变量延迟,请记住“即时”这个关键词。- @echo off
- ::步骤1
- set xcqkenl=xcqkenl00 &echo %xcqkenl%
- ::步骤2
- set xcqkenl=xcqkenl &echo %xcqkenl%
- pause
复制代码
以上代码存为批处理。
步骤1会显示echo处于关闭状态,是因为这条完整的语句之前并没有给xcqkenl赋值,所以会输出这样的结果。
步骤2会显示xcqkenl00,是因为在在步骤一中给它赋的值,并不是步骤2中的值。
要得到即时得到的值。用变量延迟。- @echo off&setlocal enabledelayedexpansion
- set a=a&echo %a%
- echo %a%
- set a=b&echo %a%
- set a=c&echo !a!
- pause
复制代码
以上,运行时,请注意每条语句的输出结果。
作者: itrui 时间: 2008-8-11 18:53
不是特别的复杂的时候基本明白。
作者: xcqkenl 时间: 2008-8-11 19:12
对头 我是 直接在cmd中运行的
作者: xcqkenl 时间: 2008-8-11 19:14
斑竹说 关于变量延迟 可以理解为 就是立即 刷新 变量的值 即斑竹说的 “即时”
很有意思
作者: batman 时间: 2008-8-11 23:11
我来补充两句:
一、在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 编辑 ]
作者: xcqkenl 时间: 2008-8-12 08:01
请问 batman 能不能讲下关于
二、可以用call来替代变量延迟的作用,大家可以在cmd中输入如下命令,再看结果
set "a=123"&echo %a%
set a=
set "a=456"&call,echo %a%
中call的运行机制呀
作者: pusofalse 时间: 2008-8-12 09:35 标题: 7楼正解
这样理解就可以了,虽然可能还是不太严谨,但我一直是这么过来的。
call的作用好多啊。调用、解析变量。
关于调用,call/?中说的已经很清楚了,可以对一个外部批处理进行调用的同时给它传递参数,也可以当前的另外一个标签进行调用,同样可以传递参数。示例:- @echo off
- call :lp1 我是参数
- goto lp2
- :lp1
- echo %1
- goto :eof
- :lp2
- echo [%1] —— %%1在我这里不管用了。
- pause>nul&exit/b
复制代码
详细请参照这篇帖子: goto for call三种句式 http://bbs.bathome.net/viewthread.php?tid=1267
关于call解释变量,如下,测试两段代码。
一、
- @echo off
- :: %windir%
- :: Purification
- :: %computername%
- :: %username%
- :: %random% %random%
- :: %time%
- for /f "delims=" %%a in (%~fs0) do echo %%a
- pause
复制代码
二、
- @echo off
- :: %windir%
- :: Purification
- :: %computername%
- :: %username%
- :: %random% %random%
- :: %time%
- for /f "delims=" %%a in (%~fs0) do call echo %%a
- pause
复制代码
请先注意两段代码的区别。。第二个只不过比第一个多了一个call,运行,分别看下两段代码的输出结果。希望你能从中总结出什么道道。
[ 本帖最后由 pusofalse 于 2008-8-12 09:55 编辑 ]
作者: CZT 时间: 2008-9-2 12:51 标题: 无法总结
Pusofalse兄:你的这两段代码,我测试及思考了很久。
但没有总结到什么,甚至越看越糊涂。都不知道他到底为什么会显示这样的结果了。
你能帮忙解释一下吗?谢了
作者: doupip 时间: 2010-10-29 14:30
很有意义的一个帖子,值得学习
作者: paladinjin 时间: 2010-11-3 11:54 标题: 回复 11楼 的帖子
一个没具体值是变量名一个是具体值
作者: l0set 时间: 2010-11-7 16:32
不同变量所对应的同来的结果会不同。
作者: hanyeguxing 时间: 2010-11-28 01:10
原帖由 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!
作者: Ryeah 时间: 2010-12-23 17:49
似懂非懂的样子。看来还得果断的重新看所有命令。
欢迎光临 批处理之家 (http://bbs.bathome.net/) |
Powered by Discuz! 7.2 |