Windows 如何在普通DOS批处理文件中模拟函数?

Windows 如何在普通DOS批处理文件中模拟函数?,windows,batch-file,cmd,dos,Windows,Batch File,Cmd,Dos,这个问题基本上是关于如何在MS-DOS/Windows命令提示符(减去扩展名)的文件本身中模拟批处理文件的功能。在命令提示符中,使用扩展名,您只需首先在批处理文件的开头调用setlocal enableextensions,然后使用call:function params调用函数,这将像在大多数其他语言中一样调用它(例如function(params))。这在DOS等(FreeDOS等)中并不容易,因为Windows XP中没有引入命令提示符扩展。解决方案似乎很难找到,但实际上比看起来更简单。基

这个问题基本上是关于如何在MS-DOS/Windows命令提示符(减去扩展名)的文件本身中模拟批处理文件的功能。在命令提示符中,使用扩展名,您只需首先在批处理文件的开头调用
setlocal enableextensions
,然后使用
call:function params
调用函数,这将像在大多数其他语言中一样调用它(例如
function(params)
)。这在DOS等(FreeDOS等)中并不容易,因为Windows XP中没有引入命令提示符扩展。

解决方案似乎很难找到,但实际上比看起来更简单。基本上,这个实现会导致批处理文件递归地调用自己,这在以后会更有意义。首先,您需要一种方法来区分函数调用和普通命令行参数。在我的示例中,为了简单起见,我将使用冒号
表示参数是一个函数。这将产生以下代码(仅为命令的一部分):

这段代码将首先设置一个变量,以获取第一个参数,并接受该参数作为函数名。接下来,我们需要转到递归调用中的那个函数,它就这么简单

goto %fn%
现在,我们需要一种方法来解释不正确的函数调用,并在批处理文件错误时终止其执行(就像任何具有正确函数调用的语言一样)。此修改将允许捕获此错误,并将立即终止批处理文件。如果你想知道的话,我把这个语句分成了一个集合,如果这个函数不存在,我就把它作为一个变量。我添加了
echo
语句以使调试更容易

goto %fn% || set err=t
if defined %err% (
    echo Undefined function: %fn%!
    goto :eof
)
因此,在这之后,您可以像正常情况下一样创建函数,因为
goto:eof
调用的行为与有无扩展时相同。下面是这个的整个批处理文件实现(我没有提到所需的转换,在这里):

必须注意的是,带扩展的函数调用机制与此实现之间的一个小区别是:必须像这样调用函数
调用%0:function args
,而不是像启用扩展时那样调用
调用:function args
。如果您不这样做,您肯定会发现难以找到的错误(错误不会让您朝正确的方向发展)

如果您想为此添加一点糖,您可以始终
设置call=call%%0
并使用
%call%:function
args


编辑:我忘记了如何实际调用函数的一个细微差别。我在主体中修复了它。

我有理由相信,在那些早期版本中,您可以调用一个辅助批处理文件,因此您可以编写一个类似于STRING2.BAT的文件

@echo off
set %1=%2%3
并通过

call string2 longstring,abcd,%wxyz%
echo concatenated string=%longstring%
(当然,这不是连接两个字符串的理想方法,它只是一个演示)

当然,拥有批处理调用本身并使用固定的参数值(如
)来修改thisbatch.bat的行为在过去是一种常见的技术,但尽管它将所有代码保存在一个批处理文件中,您将永远在批处理之间复制代码片段,并造成维护噩梦。另一种选择是创建一个单独的cleverfunction.bat文件,但传达创建一个单独文件的需要以及文件的位置是一个新的噩梦


在这些日子里,你必须给我一个虫的解决方案,这样的技术已经不可行了。

< P>如果你正在做恐龙时代的编程,你应该总是考虑恐龙时代的解决方案。p>
我使用的代码如下所示:

@回音

SETLOCAL

设置ldt=nada

回声.%ldt%

呼叫:setCurrentTime

回声.%ldt%

呼叫:setCurrentTime

回声.%ldt%

端部

回音、暂停和转到:eof

::--------------------------------------------------------

:--函数部分从下面开始

::--------------------------------------------------------

:setCurrentTime

rem****Obtem数据与时间相关:INI**********************************

对于/F“usebackq tokens=1,2 delims==”(
wmic os get LocalDateTime/VALUE 2^>NUL)中的%%i如果“%%i.”==”.LocalDateTime.”则执行该操作。设置ldt=%j

设置ldt=%ldt:~6,2%/%ldt:~4,2%/%ldt:~0,4%%ldt:~8,2%:%ldt:~10,2%:%ldt:~12,6%

rem****Obtem数据e hora corrente:职能指令手册**********************************

后藤:eof


有道理。这种实现上的差异似乎有一些合理的理由,但基本上,这种差异来自于您是只想将一个批处理文件交给某人,还是想将一个非常方便的解决方案作为一个单独的文件。我的案例基本上应该是“将其复制到文件顶部,现在您可以有效地模拟该功能,只需一点差异”,而您的案例则是“这里有一个小文件,可以直接为您提供该功能”。只是意见上的不同,最好的都属于个人喜好。哈哈。。。DOS脚本并没有那么古老。而且它肯定没有死
@echo off
set %1=%2%3
call string2 longstring,abcd,%wxyz%
echo concatenated string=%longstring%
rem call the "hello world" function
set return=line101
goto helloworld
:line101

rem now call it again
set return=line102
goto helloworld
:line102

rem ok, I'm done
goto :eof

:helloworld
echo Hello, world!
goto %return%

:eof
rem the end