关于“call :label(标签)引发的问题”的一些推测

来源:百度文库 编辑:神马文学网 时间:2024/10/02 00:39:30
关于“call :label(标签)引发的问题”的一些推测2007-06-28 00:57

前言:

cn-dos上面有人提出了下面的问题:

测试代码:
一。
@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 有意想不到的结果。???可能大家早就知道啦。
由于时间关系,我要下机啦,明天再和大家讨论这个问题。

=================================================================

本人凑了一下热闹分析了一下:

首先,使用call :label(标签)时标签前面要加冒号,如call :A;

-----------------------------------------------------------------

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

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

当时我做了下面的一些试验和推测:

先做一个试验,写一个批处理,内容为

@echo off
pause
echo a
pause

运行后先不要按任何键,在那个批处理上面右键——编辑,将echo a改为echo b,保存后转为那个正在运行的批处理的窗口,按一下任意键,结果echo出来的是b而不是a!

再做一个试验,批处理内容如下:

@echo off
pause
echo a
pause

同样运行后不要按任何键,然后把那个批处理文件删除或者重命名,接着转为批处理的运行窗口,按一下任意键,批处理直接退出而不执行下面的语句,看到一行报错的语句;

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

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

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

-----------------------------------------------------------------

回到标签的讨论上来,由于系统按照顺序执行批处理里面的代码,当执行到 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点,看看下面的代码:

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

:123
echo a
goto :EOF

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