Batch file 修复已达到的最大setlocal递归级别

Batch file 修复已达到的最大setlocal递归级别,batch-file,Batch File,我知道有人问过这个问题,但这是一个更具体的需要。我最近接受了一个挑战,试图通过windows上的批处理来创建一种简单的“编程语言”。是的。然而,编译器在返回消息之前只能处理32个setlocal。因为它们在“脚本结束”之前不会关闭,如果不是由endlocal表示,则代码x行数中的每一行都会设置1个本地值 以下是我所知道的: Endlocal用于“关闭”setlocal 如果未指示,则在脚本退出时自动关闭,仍然保留脚本局部变量。这允许setlocals-purpose-script-specifi

我知道有人问过这个问题,但这是一个更具体的需要。我最近接受了一个挑战,试图通过windows上的批处理来创建一种简单的“编程语言”。是的。然而,编译器在返回消息之前只能处理32个setlocal。因为它们在“脚本结束”之前不会关闭,如果不是由endlocal表示,则代码x行数中的每一行都会设置1个本地值
以下是我所知道的:
Endlocal用于“关闭”setlocal
如果未指示,则在脚本退出时自动关闭,仍然保留脚本局部变量。这允许setlocals-purpose-script-specific-vars在其核心仍然工作,而不会终止它
这意味着我可以在同一术语实例中执行新的批处理脚本(只需键入“%home%\software\dir.bat”),而无需关闭原始的setlocal。 新脚本可能会有另一个setlocal。这就引出了这个问题。它回到自身,可能就是这样

因此,以下是我不知道的问题:

我使用1 setlocal键入要编译的文件名,它会打开编译器脚本,每行使用1 setlocal。我尝试在编译器需要setlocal后立即在代码中输入“endlocal”(就像所有命令完成后的代码一样),但是脚本崩溃了。当我在第一个程序中尝试这样做时,它也会崩溃。

因此,我有3个选项
答:找出在何处放置end local以允许脚本运行/或找到关于消息的另一个解决方案,该解决方案不涉及使用endlocals,但我认为没有。
b:找出一个解决办法来分解超过30行的文件,但我90%肯定他们的文件不是一个有效的文件,或者在这一点上甚至有一个尝试的点,我的意思是-----我也可以尝试编程NASAS原始计算机来驱动特斯拉。那太乱了。让我们忽略选项B。
c:在这个愚蠢的项目中使用另一种语言,但再次强调的是,这是一种成批执行的脚本语言,所以让我们只解决问题的局限性,并坚持使用它。

编译器中需要的所有setlocal enabledelayedexpansion等都是将一行拆分为参数,然后分别将它们设置为%arg1%%arg2%%arg3%etc
这是“编译器”中的相关代码。如果有人想查看完整文件,请给我发消息

setlocal EnableDelayedExpansion
<"!file!" (
  for /f %%i in ('type "!file!" ^| find /c /v ""') do set /a n=%%i && for /l %%j in (1 1 %%i) do (
    set /p "line_%%j="
REM this just breaks the file into lines
  )
)
REM this then takes the first line from that respective variable and breaks it into arguments.
set i=1
set "arg!i!=%line_1: =" & set /A i+=1 & set "arg!i!=%"
setlocal EnableDelayedExpansion
nul对一些命令无效

多谢各位。
我始终可以依靠stackoverflow来实现我之上的方法。

setlocal
endlocal
的一些解释

只有使用setlocal,才能更改延迟扩展和扩展的模式

setlocal EnableDelayedExpansion
setlocal EnableExtensions
每个setlocal将当前模式(扩展、延迟扩展)和所有变量的副本推送到堆栈中

endlocal
弹出堆栈中的模式和变量

但是
CALL
命令也使用此堆栈,因此只能对在同一调用级别中调用的
setlocal
使用
endlocal

退出
/
goto:eof
将隐式执行当前调用级别的所有endlocals

对你的问题:(我不明白!)

解决方案1:在脚本开始时只使用一个
setlocal EnableDelayedExpansion
,它在脚本的生命周期内启用延迟扩展

代码示例:

@echo off 
setlocal EnableDelayedExpansion

call :load_file_to_array
call :split_line_to_args 1

exit /b

:load_file_to_array
<"!file!" (
  for /f %%i in ('type "!file!" ^| find /c /v ""') do set /a n=%%i && for /l %%j in (1 1 %%i) do (
    set /p "line_%%j="
REM this just breaks the file into lines
  )
)
exit /b 

:split_line_to_args
REM this then takes the first line from that respective variable and breaks it into arguments.
set /a i=%1
set "arg!i!=%line_1: =" & set /A i+=1 & set "arg!i!=%"
exit /b

这是一种宽泛的方式,你并不是真的围绕一个特定的问题问一个问题,它更多的是一篇带有一些随机的,模糊的问题的文章。似乎您正在寻求调试帮助。此外,这里没有编译器,批处理文件只是,文件,带有批处理的代码,没有编译。所以不要这样做。您想要什么样的答案?要简单地隐藏超过setlocal最大值的输出,请使用setlocal EnableDelayedExpansion 2>nul或setlocal 2>nul。然而,我很难理解您选择的方法,特别是为什么您的下标需要对每一行使用setlocal。对于您所描述的,使用数组似乎更合适。我想我需要更多地了解你的脚本和配套程序的功能,以及它们如何共同发挥作用,才能看到更广阔的前景。谢谢你,太棒了。我不知道为什么我没有想到只在第一个文件中设置setlocal,这样之后循环到的任何脚本都不会打开另一个。谢谢你,伙计,你的解释也很有用。
@echo off 

set "myString=abcdefg"
call :strlen return_length myString
echo %return_length%
exit /b

:strlen <resultVar> <stringVar>
(   
    setlocal EnableDelayedExpansion
    (set^ tmp=!%~2!)
    if defined tmp (
        set "len=1"
        for %%P in (4096 2048 1024 512 256 128 64 32 16 8 4 2 1) do (
            if "!tmp:~%%P,1!" NEQ "" ( 
                set /a "len+=%%P"
                set "tmp=!tmp:~%%P!"
            )
        )
    ) ELSE (
        set len=0
    )
)
( 
    endlocal
    set "%~1=%len%"
    exit /b
)