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

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

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

这样子么,不过得先弄成统一前缀格式的变量名,
可能不支持某些特殊字符,还有当前代码页不支持的字符会变成问号

for /f "tokens=1* delims==" %%a in ('set 变量名') do (
if "!aaa!" == "%aaa%" endlocal
set "%%a=%%b"
)
2

评分人数

TOP

回复 1# newswan
我想在endlocal前,使用call命令跳转到变量延迟开关外面,暂不执行endlocal,使用完变量后再关闭变量延迟开关,应当可行。

TOP


有关 !var! 续命给 %var% 是批处的一个经典话题,其中有一个 ‘坑’ 就是不能在复合语块(例如 for 或 if 括号内部)中完成,原因是cmd预处理要对复合语块中的所有 %var% 预赋值...

TOP

本帖最后由 qixiaobin0715 于 2024-8-23 10:32 编辑

个人不喜欢call、goto这样的跳转命令,所以也不是太懂,大概就是这样子:
  1. @echo off
  2. for /l %%i in (1,1,3) do (
  3.     set str=%%i
  4.     setlocal enabledelayedexpansion
  5.     set str=0!str!
  6.     call :o
  7.     endlocal
  8. )
  9. echo,####%str%
  10. pause
  11. :o
  12. echo,%str%
复制代码

TOP

  1. @echo off
  2. setlocal enabledelayedexpansion
  3. for /f "useback delims=" %%a in ("%~f0") do (
  4. set /a _n+=1
  5. set _!_n!=%%a
  6. )
  7. for /f "delims=" %%a in ('set _') do (
  8. if not defined _end (
  9. endlocal
  10. set _end=1
  11. )
  12. set %%a
  13. )
  14. set _end=
  15. set _
  16. pause
复制代码
bat小白,请多指教!谢谢!

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

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

TOP

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

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

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

不能把endlocal这道箍摘掉吗

TOP

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

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

回复 13# HOPE2021

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

TOP

回复 6# 77七

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

TOP

返回列表