2198114498 发表于 2022-6-14 22:07:07

for循环内如何endlocal&set %1=

本帖最后由 2198114498 于 2022-6-14 22:08 编辑

以下是我自己测试的代码,Test2和Test3均提示错误,
但我的需求是最外层不使用setlocal enabledelayedexpansion,所以不能用Test4。
有办法让endlocal&set %1=在for循环内成功吗?

@echo off
cd /d %~dp0

call :#Test t 11
echo %t%

call :#Test2 t 12
echo %t%

call :#Test3 t 13
echo %t%

setlocal enabledelayedexpansion
call :#Test4 t 14
echo %t%

pause
goto :eof

:#Test
setlocal enabledelayedexpansion
for /f "delims=" %%a in ("%2") do (
      set d2=%%a000
      goto :@1
)
goto :eof
:@1
endlocal &set /a %1=1%d2:~0,3%-1000
goto :eof

:#Test2
setlocal enabledelayedexpansion
for /f "delims=" %%a in ("%2") do (
      set d2=%%a000
      endlocal &set /a %1=1%d2:~0,3%-1000
      goto :eof
)
goto :eof

:#Test3
setlocal enabledelayedexpansion
for /f "delims=" %%a in ("%2") do (
      set d2=%%a000
      endlocal &set /a %1=1!d2:~0,3!-1000
      goto :eof
)
goto :eof

:#Test4
setlocal enabledelayedexpansion
for /f "delims=" %%a in ("%2") do (
      endlocal &set d2=%%a000&set /a %1=1!d2:~0,3!-1000
      goto :eof
)
goto :eof




2010techon 发表于 2022-6-15 02:49:44

本帖最后由 2010techon 于 2022-6-15 02:51 编辑

你这个用法除了第一条用的合理,后面的用法不对。。。
endlocal &set /a %1=1%d2:~0,3%-1000for是一个语句块,命令行对此有些特殊处理,比如你在里面用endlocal就会立即生效,后面就没法使用d2这个变量了。。。你可以这么用:
:#Test2
setlocal enabledelayedexpansion
for /f "delims=" %%a in ("%2") do (
      set d2=%%a000
      for %%z in (!d2!) do endlocal&echo,d2==%%z&set /a %1=1%%z-10000
   rem 或者
   rem for /f %%z in ('call echo,%%d2%%') do endlocal&echo,d2==%%z
   rem 但是这时你没法使用变量截取功能
      goto :eof
)
goto :eof
你需要仔细理解一下 setlocal 和 endlocal 的功能,setlocal 设置一个独立的变量空间
在此之后设置的变量在下一次 endlocal 之前可以使用,超出范围就不能用了。
独立语句行上的 endlocal &set。。。是个特殊情况。

2198114498 发表于 2022-6-15 09:04:28

2010techon 发表于 2022-6-15 02:49
你这个用法除了第一条用的合理,后面的用法不对。。。
for是一个语句块,命令行对此有些特殊处理,比如你 ...

谢谢,基本上有了新需要都边学边测试,对原理理解不透。
学习了,看来还是goto跳出更直接也好理解。

2010techon 发表于 2022-6-15 13:08:40

2198114498 发表于 2022-6-15 09:04
谢谢,基本上有了新需要都边学边测试,对原理理解不透。
学习了,看来还是goto跳出更直接也好理解。

:#Test
setlocal enabledelayedexpansion
for /f "delims=" %%a in ("%2") do (
      set d2=%%a000
      goto :@1
)
goto :eof
:@1
endlocal &set /a %1=1%d2:~0,3%-1000
goto :eof你这个部分逻辑上可能会有问题:当 %2 为空时 for /f "delims=" %%a in ("%2") do。。。这个for不会执行
所以会直接执行 goto :eof 返回了,但是之前你有setlocal,这时setlocal和endlocal不成对了。
当然,如果你确定 %2不会为空,那么for里面的goto :@1 就没有意义,可以和后面的 goto :eof 还有 :@1一起删掉:
:#Test
setlocal enabledelayedexpansion
for /f "delims=" %%a in ("%2") do (
      set d2=%%a000
)
endlocal &set /a %1=1%d2:~0,3%-1000
rem 这里setlocal和endlocal就不会有问题了,但是如果%2为空,set /a %1=1%d2:~0,3%-1000 将出现错误结果
goto :eof
更好的用法是这样:
:#Test
for /f "delims=" %%a in ("%2") do (
      setlocal enabledelayedexpansion
      set d2=%%a000
)
if defined d2 (endlocal &set /a %1=1%d2:~0,3%-1000)
goto :eof

2198114498 发表于 2022-6-15 17:37:46

2010techon 发表于 2022-6-15 13:08
你这个部分逻辑上可能会有问题:当 %2 为空时 for /f "delims=" %%a in ("%2") do。。。这个for不会执行
...

谢谢提醒,测试代码没有细节,实际会有很多分支,包括for未进入循环。

cxincn 发表于 2022-6-19 22:52:26

学习学习

nowayer 发表于 2023-11-7 02:10:59

dos时代菜鸟 发表于 2023-11-7 08:18:29

for 内 用 call
call setlocal enabledelayedexpansion
页: [1]
查看完整版本: for循环内如何endlocal&set %1=