本帖最后由 amwfjhh 于 2014-11-12 09:31 编辑
终于弄明白了。函数内set无法取得其值其本质还是在于变量延时与语句块之间的相互关系。
以下是原文:- :etime <begin> <end> <ret> //求时差
- setlocal enabledelayedexpansion
- Set/a "c=(!%2:~,2!-!%1:~,2!)*360000+(1!%2:~3,2!-1!%1:~3,2!)*6000+1!%2:~-5,2!!%2:~-2!-1!%1:~-5,2!!%1:~-2!,c+=-8640000*(c>>31)"
- endlocal&set %3=%c%&goto:eof
复制代码 在原文中,函数体未用括号括起来,也即函数体之间每行语句是独立的,按先后顺序执行,因此set语句下行已被正确赋值,而set %3=%c%与endlocal组成语句块,处于同一执行周期,可用%c%取其更新后的值,setlocal enabledelayedexpansion仅对set 里面的!%@:~,2!之类开启变量延时扩展,如果此处仅为纯数字引用,则无需开启。
而在加了括号后的语句中:- :_etime <begin> <end> <ret> //求时差
- (
- echo %1 %2 %3
- REM pause>nul
- %localon%
- set /a "c=(!%2:~,2!-!%1:~,2!)*360000+(1!%2:~3,2!-1!%1:~3,2!)*6000+1!%2:~-5,2!!%2:~-2!-1!%1:~-5,2!!%1:~-2!,c+=-8640000*(c>>31)"
- echo c : !c!
- %localoff%&set %3=%c%
-
- call echo %3 : %%%3%%
-
- goto :eof
- )
复制代码 由于函数体被括号引用起来,导致整个函数体组成了一个语句块,对于脚本宿主来说,它们据有相同执行周期,这样导致的结果就是,setlocal所在行与set行,endlocal行看似为三条独立语句,实则仍为一个语句块,在同一周期被执行,set /a的结果不会被其下行的%c%所接收,而由于在语句块内开启了变量延时,!c!所取的值即为实时取值,此时的实时,就严格按照语句先后顺序来执行,endlocal之后,休想再用它来得到!c!值,因此就看到如结果所显示的,在endlocal之前的echo c : !c!可以得值,但此值不可被返回给call所指定的接收变量,解决办法有两个:一是开启整个脚本的变量延时,去除函数体内的临时开关;二是去掉函数体两边的括号,将函数体内的语句由语句块变成独立的语句集合。 |