[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
返回列表 发帖

[其他] 将 setlocal 和 endlocal 之间的变量 传递到 endlocal 之后,变量的数量不定

将 setlocal 和 endlocal 之间的变量 传递到 endlocal 之后
如果,变量的名字确定,比较好办。
但是如果变量的数量不定,变量名不定,不通过临时文件,还有什么办法?
谢谢

本帖最后由 aloha20200628 于 2024-8-25 10:56 编辑

回复 1# newswan

主批通过 call 调用子批,其实是共享主批的变量环境,除非子批用 setlocal [...] 独建自己的本地变量环境,但子批最后将本地变量 ‘续命’ 给主批,还是要避免与主批的同类同名变量的覆盖问题,因此,多个子批被主批通过 call 调用的一个简捷而稳妥之策,是由主批给每个子批分配共享变量名区段(子批独建的本地变量除外)用前缀或后缀或流水号标识等方法,不必再绕经每个子批的 ‘续命’
弯道,此法不仅是针对批处,其他脚本依然... 仅供参考

TOP

本帖最后由 newswan 于 2024-8-26 09:55 编辑

最后选择这种方式
a.bat
  1. @echo off
  2. setlocal
  3. set _var1_=111
  4. call b.bat
  5. echo :1
  6. set _
  7. for /f "usebackq tokens=1,* delims==" %%a in (`set __`) do (
  8. set _b%%a=%%b
  9. set %%a=
  10. )
  11. echo :2
  12. set _
  13. endlocal
  14. pause
  15. exit/b
复制代码
b.bat
  1. @echo off
  2. setlocal enableDelayedExpansion
  3. set __var1__=value1
  4. set __var2__=value2
  5. set __var3__=value3
  6. for /f "delims=" %%a in ('set __') do (
  7. if defined _inLocal_ (endlocal)
  8. set %%a
  9. )
  10. exit/b
复制代码
个人习惯,变量用 "_" 开头,要输出的变量,用 "__" 开头

TOP

回复 3# qixiaobin0715

代码位置是在 endlocal 之外,但是逻辑上还是在 endlocal 运行之前

TOP

本帖最后由 newswan 于 2024-8-25 04:10 编辑

回复 13# HOPE2021

变量名 变量值 不够多的时候,可以,一般的脚本不会有那么多输出。
可以用把参数的方式返回。调用的地方获取整个字符串后,再进行处理。

TOP

如果比较复杂的,setlocal 隔离还是必要的,虽然隔离要麻烦些。
我现在遇到的一个情况是,以前有一个脚本,单独使用的,现在要在另一个脚本里调用,两个脚本里有变量冲突。
认为,与其改变量名,不如 setlocal ,仅仅返回需要的变量,把输出的变量名,前面加一个前缀,_a_var1
用一个通用的办法比较好些。

TOP

回复 6# 77七

这个思路用过。在 setlocal 的时候
  1. set _inlocal_=True
复制代码

TOP

回复 13# HOPE2021

我以为楼主只用SetLocal,用SetLocal EnableDelayedExpansion的话因为处理特殊字符!和^麻烦确实有时候需要关闭,要是批处理能使用变量延迟又不变量局域化就好了。
如果要复制的变量名称和数量不确定的话,应该需要像2楼那样用set列出所有变量列表。

TOP

本帖最后由 HOPE2021 于 2024-8-24 07:25 编辑

回复 12# buyiyang
如果使用变量构造命令的话,应该可以,不过这对兼容性有很大压力(不同版本的 Windows 变量内容长度限制不同),所以不可能一次性复制大量变量,也难以复制特殊字符。

既要用 endlocal 结束本地化变量环境,然后又要该环境的所有变量,不就相当于没用 endlocal 吗?好奇你的应用场景是什么,如楼上所言何不摘掉 endlocal 呢?

其实不是,有些复杂运算可能需要启用延缓环境变量,但是程序的主体不需要,所以才有这种看似“奇怪”的需求。

以下命令在 Windows 2000(版本 5.00.2195)和 Windows 11(Microsoft Windows [版本 10.0.22631.4037])测试通过,简单地实现了这种需求,仅作抛砖引玉。
  1. @echo off
  2. SetLocal EnableDelayedExpansion
  3. set /a var1=1,var2=2,var3=3
  4. echo.已启用延缓环境变量
  5. echo.var1 = !var1!, var2 = !var2!, var3 = !var3!
  6. %================================================================%
  7. %= 设定要复制的变量名列表 =%
  8. set "__varlist=var1 var2 var3"
  9. set "__command="
  10. for %%_ in (!__varlist!) do (
  11.     set "__command=!__command! "%%_=%%%%_%%""
  12. )
  13. for /f "delims=" %%_ in ('echo.!__command!') do (
  14.     echo.{%%_}
  15.     endlocal
  16.     for %%` in (%%_) do (
  17.         set %%`
  18.     )
  19. )
  20. %================================================================%
  21. set __varlist
  22. set __command
  23. echo.已禁用延缓环境变量
  24. echo.var1 = %var1%, var2 = %var2%, var3 = %var3%
  25. %= 下面一行没有任何意义,只是想说明已禁用延缓环境变量 =%
  26. echo.var1 = !var1!, var2 = !var2!, var3 = !var3!
  27. pause
复制代码
2

评分人数

Why join the navy, if you can be a pirate? - Steve Jobs

TOP

不临时存储上一个环境的变量的话,应该是没有办法了。
正如你所言,如果变量的名称确定比较好办,可以利用预处理针对性复制变量;但是如果变量的数量不定名称不定,意味着要完整复制变量环境,而这明显违背了使用 endlocal 的初心:
既要用 endlocal 结束本地化变量环境,然后又要该环境的所有变量,不就相当于没用 endlocal 吗?好奇你的应用场景是什么,如楼上所言何不摘掉 endlocal 呢?

TOP

不能把endlocal这道箍摘掉吗

TOP

本帖最后由 77七 于 2024-8-23 16:00 编辑

成也预处理,败也预处理,老手在利用预处理;新手败给预处理
  1. setlocal
  2. set n=1
  3. endlocal & echo %n%
复制代码

  1. set n=1& echo %n%
复制代码



变量延迟扩展表示不服,爱用哪个就用哪个;关闭,只能用预处理

  1. set n=1& setlocal enabledelayedexpansion &echo %%n%%=[%n%](预处理=空值)  ^^!n^^!=[!n!](变量延迟扩展值)&endlocal & echo set "n=%n%"
复制代码
bat小白,请多指教!谢谢!

TOP

本帖最后由 qixiaobin0715 于 2024-8-23 15:46 编辑

要注意,5楼代码跳转后,执行标签后面的代码时,变量延迟开关并没有关闭,返回时才关闭,每个完整循环完成关闭一次,特殊情况时有用。

TOP

回复 7# aloha20200628
第2轮好牌!!!
前不久我也遇到过这种情况,都是使用临时文件中转的,好麻烦。这个有用!简洁!

TOP

本帖最后由 aloha20200628 于 2024-8-23 14:38 编辑


运行以下代码可见》4种实况说明 ‘延迟变量’ 开启前后的值变及其 ‘续命’ 的一个有效方法...
  1. @echo off &setlocal
  2. echo,第一轮
  3. set/a "v1=1,v2=2,v3=3"
  4. echo, 未开延迟变量》v1=%v1%,v2=%v2%,v3=%v3%
  5. setlocal enabledelayedexpansion
  6. set "v1=11" &set "v2=12" &set "v3=13"
  7. echo, 开启延迟变量》v1=%v1%,v2=%v2%,v3=%v3%
  8. endlocal
  9. echo, 关闭延迟变量》v1=%v1%,v2=%v2%,v3=%v3%
  10. echo,第二轮(续命之道)
  11. set/a "v1=1,v2=2,v3=3"
  12. echo, 未开延迟变量》v1=%v1%,v2=%v2%,v3=%v3%
  13. setlocal enabledelayedexpansion
  14. set "v1=21" &set "v2=22" &set "v3=23"
  15. echo, 开启延迟变量》v1=%v1%,v2=%v2%,v3=%v3%
  16. endlocal & set "v1=%v1%" &set "v2=%v2%" &set "v3=%v3%"
  17. echo, 关闭延迟变量》v1=%v1%,v2=%v2%,v3=%v3%
  18. echo,第三轮(复合语块-if)
  19. set/a "v1=1,v2=2,v3=3"
  20. echo, 未开延迟变量》v1=%v1%,v2=%v2%,v3=%v3%
  21. if 1 equ 1 (
  22. setlocal enabledelayedexpansion
  23. set "v1=31" &set "v2=32" &set "v3=33"
  24. echo, 开启延迟变量》v1=%v1%,v2=%v2%,v3=%v3%
  25. endlocal & set "v1=%v1%" &set "v2=%v2%" &set "v3=%v3%"
  26. )
  27. echo, 关闭延迟变量》v1=%v1%,v2=%v2%,v3=%v3%
  28. echo,第四轮(复合语块-for)
  29. set/a "v1=1,v2=2,v3=3"
  30. echo, 未开延迟变量》v1=%v1%,v2=%v2%,v3=%v3%
  31. for /l %%n in (1,1,1) do (
  32. setlocal enabledelayedexpansion
  33. set "v1=41" &set "v2=42" &set "v3=43"
  34. echo, 开启延迟变量》v1=%v1%,v2=%v2%,v3=%v3%
  35. endlocal & set "v1=%v1%" &set "v2=%v2%" &set "v3=%v3%"
  36. )
  37. echo, 关闭延迟变量》v1=%v1%,v2=%v2%,v3=%v3%
  38. endlocal&pause&exit/b
复制代码
2

评分人数

TOP

返回列表