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