从子程序返回变量,不工作......为什么? [英] return variable from subroutine, not working... why?

查看:30
本文介绍了从子程序返回变量,不工作......为什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为了在文本文件中的变量中存储多行,我使用了这个问题的答案:https://stackoverflow.com/a/10624240/1513458

In order to store multiple lines inside a variable from a text file, I am using the answer from this question: https://stackoverflow.com/a/10624240/1513458

内联使用此脚本并解析大文件给了我最大的 setlocal 错误.所以为了解决这个问题,我把脚本放在一个子程序中,并从我需要它的行调用它.

Using this script inline and parsing large files gave me a maximum setlocal error. So to counter this, I put the script in a subroutine, and called it from the line(s) i needed it in.

在子例程终止之前,在子程序底部的回声会很好地输出预期的结果……但是回到最初调用它的顶部,变量是空的.这是为什么?

An echo at the bottom of the subroutine before it terminates would output the expected result fine... but back at the top where it was originally called, the variable is empty. Why is that?

这是脚本的简化版本:

setlocal EnableDelayedExpansion
set sourcefile=cc1
call :readfile %sourcefile%
echo !insert!
goto :EOF

:readfile
SETLOCAL DisableDelayedExpansion
set "insert="
FOR /F "usebackq delims=" %%a in (`"findstr /n ^^ %SOURCELOC%\%1.txt"`) do (
    set "line=%%a"
    SETLOCAL EnableDelayedExpansion
    set "line=!line:#=#S!"
    set "line=!line:*:=!"
    for /F "delims=" %%p in ("!insert!#L!line!") do (
        ENDLOCAL
        set "insert=%%p"
    )
)
SETLOCAL EnableDelayedExpansion
if defined insert (
set "insert=!insert:~2!"
set ^"insert=!insert:#L=^

!"
set "insert=!insert:#S=#!"
)
rem A echo !insert! here would output the expected result
goto :EOF

非常感谢您的帮助.Batch 显然不适合我,但我需要坚持下去.

Thanks so much for all your help. Batch is clearly not meant for me, but i need to tough this one through.

推荐答案

你的 :readfile 例程在顶部有 SETLOCAL 来本地化环境变化.当例程结束时,会为例程中实例化的每个活动 SETLOCAL 执行一个隐式 ENDLOCAL.这样环境就恢复到调用前的状态了.

Your :readfile routine has SETLOCAL at the top that localizes environment changes. When a routine ends, there is an implicit ENDLOCAL executed for every active SETLOCAL that was instantiated within the routine. So the environment is restored to the state that existed prior to the call.

不需要被调用的子程序.您之前的代码在 FOR 循环中必须具有 SETLOCAL 而没有 ENDLOCAL.这将导致最大 SETLOCAL 错误.现在你的 FOR 循环已经配对了 SETLOCAL/ENDLOCAL,所以没问题了.

There is no need for a called subroutine. Your earlier code must have had SETLOCAL without an ENDLOCAL within the FOR loop. That would cause the max SETLOCAL error. Now your FOR loop has paired SETLOCAL/ENDLOCAL, so no more problem.

可以跨越 ENDLOCAL 屏障传输任何值,但它使用了一种先进的技术.

It is possible to transport any value accross the ENDLOCAL barrier, but it uses an advanced technique.

一些简单的重组避免了这样做的需要.但要小心 - 批处理变量不能包含超过 8192 个字符.

Some simple restructuring avoids the need to do that. But be careful - no batch variable can contain more than 8192 characters.

setlocal disableDelayedExpansion
set sourcefile=cc1

set "insert="
for /f "delims=" %%a in ('findstr /n "^" "%SOURCELOC%\%~1.txt"') do (
  set "line=%%a"
  setlocal EnableDelayedExpansion
  set "line=!line:#=#S!"
  set "line=!line:*:=!"
  for /f "delims=" %%p in ("!insert!#L!line!") do (
    endlocal
    set "insert=%%p"
  )
)
setlocal EnableDelayedExpansion
if defined insert (
set "insert=!insert:~2!"
set ^"insert=!insert:#L=^

!"
set "insert=!insert:#S=#!"
)
echo !insert!


编辑

这里有一个解决方案,演示了跨ENDLOCAL边界返回任何值(除非它不支持回车.有一个简单的扩展支持回车).该例程将给出正确的结果,无论它是在启用还是禁用延迟扩展的情况下调用的.该技术由 DosTips 用户 jeb 在此处开发:http://www.dostips.com/forum/viewtopic.php?f=3&t=1839,在这里:http://www.dostips.com/forum/viewtopic.php?p=6930#p6930.您会在那里找到有关其工作原理的一些解释,但不适合胆小的人.

Here is a solution that demonstrates returning any value across the ENDLOCAL border (except it does not support carriage return. There is a simple extension that supports carriage return). The routine will give the correct result, regardless whether it was called with delayed expansion enabled or disabled. The technique was developed by DosTips user jeb here:http://www.dostips.com/forum/viewtopic.php?f=3&t=1839, and here: http://www.dostips.com/forum/viewtopic.php?p=6930#p6930. There you will find some explanation as to how it works, but it is not for the faint of heart.

@echo off
setlocal enableDelayedExpansion
set sourceloc=.
set sourcefile=test
set ^"LF=^

^"
call :readFile "%sourcefile%"
echo(!insert!
exit /b

:readFile
setlocal
set "notDelayed=!"

setlocal disableDelayedExpansion
set "insert="
for /f "delims=" %%a in ('findstr /n "^" "%SOURCELOC%\%~1.txt"') do (
  set "line=%%a"
  setlocal EnableDelayedExpansion
  set "line=!line:%%=%%J!"
  set "line=!line:*:=!"
  for /f "delims=" %%p in ("!insert!%%~L!line!") do (
    endlocal
    set "insert=%%p"
  )
)
setlocal enableDelayedExpansion
if defined insert (
  set "insert=!insert:"=%%~K!"
  if not defined notDelayed set "insert=!insert:^=^^^^!"
)

if defined insert if not defined notDelayed set "insert=%insert:!=^^^!%" Do not remove!
set "replace=%% """"
for %%L in ("!LF!") do for /f "tokens=1,2" %%J in ("!replace!") do (
  endlocal
  endlocal
  endlocal
  set "insert=%insert%" Do not remove!
)
exit /b

这篇关于从子程序返回变量,不工作......为什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆