Board logo

标题: call 调用:label(标签)引发的问题[已结] [打印本页]

作者: stornager     时间: 2007-6-27 21:23    标题: call 调用:label(标签)引发的问题[已结]

测试代码:
一。
@echo off
echo.
echo.
call %^(set^)%(echo I love you.)%
pause

:%^(set^)%(echo I love you.)%
set n=1 2 3 4 5 6 7 8
echo    %n% %n% %n% %n%
echo                      %1% %1% %1% %1%
ping -n 3 127.1>nul
goto :eof
二。

@echo off
echo.
echo.
call %^(set&&echo I love you.^)%
pause

:%^(set&&echo I love you.^)%
set n=1 2 3 4 5 6 7 8
echo    %n% %n% %n% %n%
echo                      %1% %1% %1% %1%
ping -n 3 127.1>nul
goto :eof


经过分析认为:call 调用的标签不能含有系统内置命令或外部命令,否则就会得不到理想结果。请大家多测试!!!
今天晚上,在cmd里测试call,发现call date 有意想不到的结果。???可能大家早就知道啦。
由于时间关系,我要下机啦,明天再和大家讨论这个问题。


[ Last edited by stornager on 2007-6-28 at 11:32 PM ]
作者: wudixin96     时间: 2007-6-27 21:28
不是经常用call echo %%a%%等吗?
作者: zh159     时间: 2007-6-27 21:34
调用标签也必须包含“:”号
作者: lxmxn     时间: 2007-6-27 21:47


  Quote:
Originally posted by stornager at 2007-6-27 21:23:
经过分析认为:call 调用的标签不能含有系统内置命令或外部命令,否则就会得不到理想结果。请大家多测试!!!

我测试没什么问题,比如“call :date”:
@echo off
echo Starting...
call :date
echo End...
exit/b

:date
echo This is the label :date line
echo Please press any key to exit
pause


  Quote:
今天晚上,在cmd里测试call,发现call date 有意想不到的结果。???可能大家早就知道啦。
由于时间关系,我要下机啦,明天再和大家讨论这个问题。

有什么意外结果?

  Quote:
G:\>call date
当前日期: 2007-06-27 星期三
输入新日期: (年月日)

G:\>date
当前日期: 2007-06-27 星期三
输入新日期: (年月日)

G:\>


作者: dikex     时间: 2007-6-27 21:56
call调用标签时标签可以有“:”也可以没有,当没有时,而标签名恰好为某命令名时,系统就当你是想调用那个命令了;
指代不清的结果,平时养成 call :标签名 的习惯比较好
作者: lxmxn     时间: 2007-6-27 22:47


  Quote:
Originally posted by dikex at 2007-6-27 21:56:
call调用标签时标签可以有“:”也可以没有,当没有时,而标签名恰好为某命令名时,系统就当你是想调用那个命令了;
指代不清的结果,平时养成 call :标签名 的习惯比较好

call 调用标签的时候不能没有:号吧?试试。
作者: dikex     时间: 2007-6-27 22:49
可以的,我很久以前也是不用的,但后来如了楼主类似的问题,于是以后都加上了冒号了
作者: lxmxn     时间: 2007-6-27 22:51
你测试过了没有?
作者: stornager     时间: 2007-6-27 23:01


  Quote:
Originally posted by lxmxn at 2007-6-27 10:51 PM:
你测试过了没有?

谢谢斑竹的指教,但是加了:命令提示符提示系统找不到指定的标签。:o:o:o对于call date的输出结果我感到惊奇,是因为我几乎没有直接在命令行敲入date,现在想通啦。

@echo off
echo.
echo.
call :%^(set^)%
pause

:%^(set^)%
set n=1 2 3 4 5 6 7 8
echo    %n% %n% %n% %n%
echo                      %1% %1% %1% %1%
ping -n 3 127.1>nul
goto :eof

这个批处理便是一个例子。

[ Last edited by stornager on 2007-6-27 at 11:17 PM ]
作者: dikex     时间: 2007-6-27 23:12


  Quote:
Originally posted by lxmxn at 2007-6-27 10:51 PM:
你测试过了没有?

倒……倒……倒……

我搞错了……
还以为是goto,原来是call……
call需要加冒号的……
(犯傻中)
作者: lxmxn     时间: 2007-6-27 23:35


  Quote:
Originally posted by stornager at 2007-6-27 23:01:

谢谢斑竹的指教,但是加了:命令提示符提示系统找不到指定的标签。:o:o:o对于call date的输出结果我感到惊奇,是因为我几乎没有直接在命令行敲入 ...

之所以会出现“系统找不到指定的批处理标签 -”的错误提示,是因为“call :%^(set^)%”的时候,系统把“^(set^)”看作是一个变量,但是你并没有给他赋值,所以导致它的值为空,此时就相当于“ call :”,调用了一个不存在的标签,系统自然就给出了上面的提示。

下面给出一个例子,希望对你理解call有帮助。
@echo off
echo Beginning of test
set ^^(set^^)=Batch
call :%^(set^)%
echo End of test
pause&exit/b

:%^(set^)%
set n=1 2 3 4 5 6 7 8
echo    %n% %n% %n% %n%
echo                      %1% %1% %1% %1%
ping -n 3 127.1>nul
goto :eof

:Batch
echo This script is worked

作者: stornager     时间: 2007-6-27 23:42
关于上面的代码我在网吧测试了3个多小时,不论怎样改变标签本身的名称,只要其内含有系统内置命令或外部命令都不易得到正确的输出结果。还有我在命令行打入下面一串命令,为何不能得到值123(系统没有提示错误):
call (
echo.
set n=123
echo %n%
)
作者: stornager     时间: 2007-6-27 23:55


  Quote:
Originally posted by lxmxn at 2007-6-27 11:35 PM:

之所以会出现“系统找不到指定的批处理标签 -”的错误提示,是因为“call :%^(set^)%”的时候,系统把“^(set^)”看作是一个变量,但是你并没有给他 ...

再次谢谢斑竹的指教,但是下面代码的date不需要赋值吧???结果同样是系统找不到指定的批处理标签。

@echo off
echo.
call :%^(date^)%
pause&exit/b

:%^(date^)%
set n=1 2 3 4 5 6 7 8
echo    %n% %n% %n% %n%
echo                      %1% %1% %1% %1%
ping -n 3 127.1>nul
goto :eof
作者: dikex     时间: 2007-6-28 00:37
首先,是前标签要加冒号,这个上面已经说了;

第二,貌似和标签名后面的括号有关:

看看下面的代码:
call :1(123)
pause
goto :EOF

:1(123)
echo a
goto :EOF
运行时发现报错,而出错提示是“系统找不到指定的批处理标签 - 1”,括号后面的不见了,在看看下面的代码:
call :1123)
pause
goto :EOF

:ddd
echo a
goto :EOF
这是出错提示变为了“系统找不到指定的批处理标签 - 1123)”;

再测试一个代码:
call :1(123)
pause
goto :EOF

:1
echo a
goto :EOF
这时居然可以成功调用了!


我推测是那个括号(的问题了,如果标签名里面包含有(,那么系统将会忽略它本身和它后面的所有字符,于是就会报错了;%!等变量里面可以

存在(,因为系统会在命令执行前把相关的变量替换掉;

而具体楼主的那段代码,由于前面的%^(set^)%没有复制(即为空),而(和它后面的又被忽略了,所有出现了“系统找不到指定的批处理标签 -”的错误提示也就可以解释了;


第三,我想这个应该很可能和系统执行批处理文件的方法有一定的关系:

记得以前有人问过怎样使得执行下面的类似代码运行时不会提示“找不到批处理文件”(拖到cmd窗口下执行可以看到相关信息);
echo a
del %0
当时我做了下面的一些试验和推测:

  Quote:
先做一个试验,写一个批处理,内容为
@echo off
pause
echo a
pause
运行后先不要按任何键,在那个批处理上面右键——编辑,将echo a改为echo b,保存后转为那个正在运行的批处理的窗口,按一下任意键,

结果echo出来的是b而不是a!

再做一个试验,批处理内容如下:
@echo off
pause
echo a
pause
同样运行后不要按任何键,然后把那个批处理文件删除或者重命名,接着转为批处理的运行窗口,按一下任意键,批处理直接退出而不执行下

面的语句,隐约看到一行报错的语句;


关于这个,以下为个人猜测:

批处理运行时并不会一开始就将所有的代码载入内存,而是每执行完一行才载入下一行的代码,于是我们就产生了试验里面中途改变代码后执

行的是修改后的代码;

具体到楼主的那个批处理,由于批处理在运行时把自身删除了,在执行完那个del的命令后系统想往下读取下一行命令时却发现找不到那个批处

理文件,于是就报错了。

原贴:http://www.cn-dos.net/forum/viewthread.php?tid=31094


回到标签的讨论上来,由于系统按照顺序执行批处理里面的代码,当执行到 call :标签名,如果有标签名里面含有变量,系统会替换掉那个变

量,但由于后面的需要被调用的标签上面的变量并没有被替换,这时就会出现找不到标签的错误信息了,看看下面的几个代码:
set "^date^=123"
call :%^date^%
pause
goto :EOF

:123
echo a
goto :EOF
这个执行成功了,从回显那里可以看到被执行的代码是 call :123 ,也就是执行call是系统就已经把%^date^%替换为123了,再看看下面的代

码:
set "^date^=123"
call :%^date^%
pause
goto :EOF

:%^date^%
echo a
goto :EOF
系统提示“系统找不到指定的批处理标签 - 123”,同样系统已经把call后面的标签替换了,但系统并没有替换后面的被调用的那个标签,于

是系统就报错了。


综合2、3点,看看下面的代码:

[code]
set "(date)=123("
call :%(date)%456
pause
goto :EOF

:123
echo a
goto :EOF
[code]

如果上面的看明白了,那应该可以猜出这个代码是可以正常运行的

[ Last edited by dikex on 2007-6-28 at 12:41 AM ]
作者: zh159     时间: 2007-6-28 01:27
以前就试过,标签不能使用变量方式,倒是goto、call可以使用变量
call :1(123)
pause
goto :EOF

:1
echo %1
goto :EOF
这个方式会把(123)作为%1,但是call :1(123)(321)中的(321)却不能成为%2,(123)(321)作为整体为%1,需要%2以后的还得空格

[ Last edited by zh159 on 2007-6-28 at 10:31 AM ]
作者: stornager     时间: 2007-6-28 23:09
谢谢dikex和zh159兄的大力指教,很抱歉没有及时回复两位的答复,对于此问题我总算搞懂啦!
由于偶没有电脑且爱好dos批处理,因此一有空余时间便到网吧上网,可是网吧的机子不是每台都好,其ie浏览器常常出问题,导致我不能正常登陆论坛,今天就遇到了这种情况!!!!!!!!!!!!!!!
作者: kgdetg1127     时间: 2007-12-3 22:32
好文章啊,顶上去!
作者: moniuming     时间: 2008-1-18 10:25
谢谢各位的分析,我以前一直不太清楚call的用法,特别是像call :1(123)这样在标签后还跟着东西的时候,现在总算明白一些了,再次感谢!