中国DOS联盟论坛

中国DOS联盟

-- 联合DOS 推动DOS 发展DOS --

联盟域名:www.cn-dos.net  论坛域名:www.cn-dos.net/forum
DOS,代表着自由开放与发展,我们努力起来,学习FreeDOS和Linux的自由开放与GNU精神,共同创造和发展美好的自由与GNU GPL世界吧!

游客:  注册 | 登录 | 命令行 | 会员 | 搜索 | 上传 | 帮助 »
中国DOS联盟论坛 » DOS批处理 & 脚本技术(批处理室) » [已结]寻willsort !!,DOS能不能嵌套多层变量?
« [1] [2] »
作者:
标题: [已结]寻willsort !!,DOS能不能嵌套多层变量? 上一主题 | 下一主题
GOTOmsdos
铂金会员

C++启程者


积分 5154
发帖 1827
注册 2003-7-18
状态 离线
『楼 主』:  [已结]寻willsort !!,DOS能不能嵌套多层变量?

最近做东东,发现DOS好象不能嵌套多层变量,加了COMMAND /C 也没大用,顶多多显示一层
比如,  有%VAR%=10,把VAR赋给%1,,,,  就不能用%%1%来取到10,
同理,SET VAR2=VAR, %%VAR%%也不能取到10,
也就是说,如果想用另一个变量同时取到某个变量名本身及其值! 这样就不方便了,
比如,我上边的修改游戏成绩:
有很多对值,一对值就是两个项目(用变量描述,比如T1表示第一号赛道,%T1%表示通过的次数),加起来就是60变量!
但通过一个%1解决不了.如下:
把T1 T2 T3...用SHIFT赋给%1, 用%%1%取到值,但不能嵌套
用FOR %%A IN (1 2 3 ....) DO CALL XXX T%%A %T%%A% 也不能嵌套
所以,害的我要列出60个变量!!
??

[ Last edited by HAT on 2008-11-3 at 20:36 ]

2005-4-27 00:00
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
chenhui530
高级用户





积分 772
发帖 273
注册 2004-10-23
状态 离线
『第 2 楼』:  



  Quote:
以下是引用GOTOmsdos在2005-4-27 0:01:56的发言:


最近做东东,发现DOS好象不能嵌套多层变量,加了COMMAND /C 也没大用,顶多多显示一层
比如,  有%VAR%=10,把VAR赋给%1,,,,  就不能用%%1%来取到10,
同理,SET VAR2=VAR, %%VAR%%也不能取到10,
也就是说,如果想用另一个变量同时取到某个变量名本身及其值! 这样就不方便了,
比如,我上边的修改游戏成绩:
有很多对值,一对值就是两个项目(用变量描述,比如T1表示第一号赛道,%T1%表示通过的次数),加起来就是60变量!
但通过一个%1解决不了.如下:
把T1 T2 T3...用SHIFT赋给%1, 用%%1%取到值,但不能嵌套
用FOR %%A IN (1 2 3 ....) DO CALL XXX T%%A %T%%A% 也不能嵌套
所以,害的我要列出60个变量!!
??

DOS在使用FOR语句的时候是不能进行多个变量循环的~
以前我也遇到这种情况



http://www.msfans.net/bbs/
2005-4-27 00:00
查看资料  发送邮件  发短消息 网志  OICQ (77740821)  编辑帖子  回复  引用回复
GOTOmsdos
铂金会员

C++启程者


积分 5154
发帖 1827
注册 2003-7-18
状态 离线
『第 3 楼』:  

好象FOR之外的其他情况也是这样的..

2005-4-27 00:00
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
willsort
元老会员

Batchinger


积分 4432
发帖 1512
注册 2002-10-18
状态 离线
『第 4 楼』:  

Re GOTOmsdos:
  这是个很有代表性的问题。
  变量不能递归引用,这源于变量标识符'%'的特性。它是一个转义字符,英文是Escape character,有人将它译为“脱字符”或者“逃逸字符”。这很形象,因为它每被命令解释器解释一次,就脱一层或者说逃逸一次,比如%%%%会变成%%,%%会变成%,%会直接消失并且转义后面的字符,这类似C语言中的'\'。所以在变量嵌套引用时,多个%叠加使用,会出现脱字符的现象,而并不会如你想象的那样工作。另外,即时'%'没有叠加,类似于这样,'%prename_%mainname%_sufname%',也只会将第二个'%'认作变量 'prename_' 的名字结束标志,而非 'mainname' 的开始标志,仍然无法实现你原定的意图。
  解决的方法很简单,现在比较忙,没有多少时间详细解释。现给你一个实例,相信不难看懂的,主要还是利用%的“逃逸”特性,只不过“逃逸”的顺序有所不同。

  Quote:
:: NestRef.bat - 变量嵌套引用实例
:: Will Sort - 2005/04/27 - CMD@WinXP
@echo off
if "%1"==":" goto %2
:Main
for %%e in (T1 T2 T3 T4 T5 T6) do set %%e=value_of_%%e
call %0 : Loop T1 T2 T3 T4 T5 T6
for %%e in (T1 T2 T3 T4 T5 T6) do set %%e=
if exist _NestRef.bat del _NestRef.bat

:Loop
if "%3"=="" goto end
echo set value=%%%3%%>_NestRef.bat
call _NestRef.bat
echo %3='%value%'
shift
goto loop
:end

[此贴子已经被作者于2005-4-27 16:06:42编辑过]






※ Batchinger 致 Bat Fans:请访问 [讨论]批处理编程的异类 ,欢迎交流与共享批处理编程心得!
2005-4-27 00:00
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
GOTOmsdos
铂金会员

C++启程者


积分 5154
发帖 1827
注册 2003-7-18
状态 离线
『第 5 楼』:  

有启发! 我刚才试了下,可以。%%1%是脱落了一层。不过好象%%ABC%%不会脱落啊。除了脱落关键是要先ECHO

2005-4-27 00:00
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
willsort
元老会员

Batchinger


积分 4432
发帖 1512
注册 2002-10-18
状态 离线
『第 6 楼』:  

Re GOTOmsdos:  “除了脱落关键是要先ECHO”  %%%3%% 在 echo 之前就被命令解释器转义了,其中前两个和后两个%“脱落”成一个%,%3被转义为实际的变量名,如果此时%3是T1,则 echo 一句就被转义成了:  echo set value=%T1%>_NestRef.bat  当然,这只是命令解释器的内部形式,在批处理中是看不到的,但是如果你把>_NestRef.bat和文头的@echo off去掉,就会在命令行中看到类似的形式“set value=%T1%”。  至于 %%ABC%% ,你改成 %%%ABC%%% 就好了。



※ Batchinger 致 Bat Fans:请访问 [讨论]批处理编程的异类 ,欢迎交流与共享批处理编程心得!
2005-4-28 00:00
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
GOTOmsdos
铂金会员

C++启程者


积分 5154
发帖 1827
注册 2003-7-18
状态 离线
『第 7 楼』:  

1  既然在 echo 之前就被命令解释器转义了,那么是不是不用ECHO也行?2   我试过几次了,%%ABC%% 没有脱落呀..如下:set ab=qweset abc=abecho md %%abc%%>test.battest运行后,就执行了md qwe(%abc%是ab, %%abc%%就是qwe.没有脱落呀)

2005-4-28 00:00
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
GOTOmsdos
铂金会员

C++启程者


积分 5154
发帖 1827
注册 2003-7-18
状态 离线
『第 8 楼』:  

发现,%%ABC%%确实不行,%%%ABC%%%才行...

2005-4-28 00:00
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
willsort
元老会员

Batchinger


积分 4432
发帖 1512
注册 2002-10-18
状态 离线
『第 9 楼』:  

Re GOTOmsdos:  1  既然在 echo 之前就被命令解释器转义了,那么是不是不用ECHO也行?  变量串的转义只有命令解释器能实现,也就是在它读取Bat中的命令行时;你可以尝试不改 echo 那句,然后直接注释掉 @echo off,然后你可以在命令行观察到 echo 一句的原形了。  但是,这并不是意味着可以轻易舍弃 echo ,因为我们的程序实际上是进行了二次转义,第一次将 '%%%3%% '转成了 %T1% (或者其他变量名),第二次则将 %T1% 转成了 value_of_T1。要实现二次转义,必须让命令解释器读取二次Bat(或者命令行也有可能),而要两次读取,就必须产生中间的临时bat,此时 echo 是最佳也最简单的选择。



※ Batchinger 致 Bat Fans:请访问 [讨论]批处理编程的异类 ,欢迎交流与共享批处理编程心得!
2005-4-28 00:00
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
GOTOmsdos
铂金会员

C++启程者


积分 5154
发帖 1827
注册 2003-7-18
状态 离线
『第 10 楼』:  终于成功地运用了DOS的变量嵌套!从而解决了通过"递减和递增

这个ECHO还真是关键呢..
终于成功地运用了DOS的变量嵌套!从而解决了通过"递减和递增"简化了WBAT的简易DOS浏览器!!!
"递减和递增"简化是最简化的...(写出来的变量只用了区区三个!,小小WBAT和GET就实现了浏览几乎无限制的深层目录及其文件!,也可顺带编辑文本文件,执行可执行程序,批处理程序,也可随时把用户的目录赋给一个变量....麻雀虽小,五脏具全..并且支持带间隔的长名目录和中文!) 共大家参考,尤其是学习WBAT和GET的...相信会有很大帮助的!..
很满意! 再次感谢WILLSORT!
简化了的WBAT如下DOS71下测试成功!) 要求: 加载DOSLFN,正确加载TW
@echo off
goto begin
:dirbars "上一级—→"[x]
[退  出]
[预  选]
[看文件]
[看目录]
:
:filebars "   上一级—→"[x]
[退  出]
[运行批处理文件]
[运行可执行文件]
[编辑文本文件]
[查看文件信息]
:
:begin
if exist drive.txt copy drive.txt dir0.txt>nul
if exist dir0.txt goto 0dir
wbat cls ! box "没有驱动器!" 退出
goto end
:0dir
set get=0
:dir0
call w.bat list dir%get%.txt
if errorlevel 100 goto end
:putdisk
if not exist notready.txt goto dirbar1
find /i "%wbat%" notready.txt>nul
if errorlevel 1 goto dirbar1
wbat box "您还没有在%wbat%盘放入盘片!" 重试
call diskfind
goto putdisk
:dirbar1
set get=1
set dir%get%=%wbat%
:dirbars1
wbat box @%0:dirbars
if errorlevel 100 goto dirbsub1
if errorlevel 4 goto dir1
if errorlevel 3 goto flist1
if errorlevel 2 goto pikdir1
goto end
:dir1
if %get%==0 goto dir0
if %get%==1 goto rootdir
echo @echo off>nestvar.bat
echo dir "%%dir%get%%%" /b/ad/one>>nestvar.bat
command /c call nestvar>dir%get%.txt
goto subdir
:rootdir
dir %dir1%\ /b/ad/one>dir1.txt
:subdir
get f dir%get%.txt /vfsize>nul
if not "%fsize%"=="0" goto dir1y
wbat box "没有子目录!" 上一级,退出
if errorlevel 2 goto end
goto dirbars1
:dir1y
call w.bat list dir%get%.txt
if errorlevel 100 goto dirbars1
get r "+" %get% /w1 /vgetadd1>nul
echo set dir%getadd1%=%%dir%get%%%\%wbat%>nestvar.bat
call nestvar
wbat box @%0:dirbars
if errorlevel 100 goto dir1y
if errorlevel 4 goto dir2
if errorlevel 3 goto flist2
if errorlevel 2 goto pikdir2
goto end
:flist1
if %get%==1 goto rootfile
echo @echo off>nestvar.bat
echo dir "%%dir%get%%%" /b/a-d/one>>nestvar.bat
command /c call nestvar>flist%get%.txt
goto subfile
:rootfile
dir %dir1%\ /b/a-d/one>flist1.txt
:subfile
get f flist%get%.txt /vfsize>nul
if not "%fsize%"=="0" goto flist1y
wbat box "没有文件!" 上一级,退出
if errorlevel 2 goto end
goto dirbars1
:flist1y
call w.bat list flist%get%.txt
if errorlevel 100 goto dirbars1
:fbars1
wbat box @%0:filebars
if errorlevel 100 goto flist1y
if errorlevel 5 goto info1
if errorlevel 4 goto text1
if errorlevel 3 goto exec1
if errorlevel 2 goto bat1
goto end
:info1
echo @echo off>nestvar.bat
echo dir "%%dir%get%%%\%wbat%" /a>>nestvar.bat
command /c call nestvar>info1.txt
wbat list info1.txt
goto fbars1
:text1
echo @echo off>nestvar.bat
echo edit "%%dir%get%%%\%wbat%">>nestvar.bat
call nestvar
goto fbars1
:exec1
echo @echo off>nestvar.bat
echo "%%dir%get%%%\%wbat%">>nestvar.bat
call nestvar
goto fbars1
:bat1
echo @echo off>nestvar.bat
echo "%%dir%get%%%\%wbat%">>nestvar.bat
call nestvar
goto fbars1
:pikdir1
echo @echo off>nestvar.bat
echo set gamesave=%%dir%get%%%>>nestvar.bat
call nestvar
goto end
:dirbsub1
get r "-" %get% /w1>nul
goto dir1
:dir2
get r "+" %get% /w1>nul
goto dir1
:flist2
get r "+" %get% /w1>nul
goto flist1
:pikdir2
get r "+" %get% /w1>nul
goto pikdir1
:end

[此贴子已经被作者于2005-4-29 2:51:28编辑过]




2005-4-29 00:00
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
willsort
元老会员

Batchinger


积分 4432
发帖 1512
注册 2002-10-18
状态 离线
『第 11 楼』:  

Re GOTOmsdos:  我对Wbat没有研究,只是看了一下程序的大致框架,感觉还有精简的空间。  比如:info1,:text1,:exec1, :bat1等,还有 :dir2,:flist2,:pkdir2等都有许多重复性的代码。向 netvar.bat 中写入 @echo off  也是不必要的,因为被调用的批处理会继承调用者的 echo 状态。  另外,有一种模糊的感觉,就是你的程序模块分划似乎不太合理,造成了类似 :dir2 :flist2 等泛义标签的存在,也在一定程度上造成了重复代码的出现。希望你能做出更大的改进!



※ Batchinger 致 Bat Fans:请访问 [讨论]批处理编程的异类 ,欢迎交流与共享批处理编程心得!
2005-4-29 00:00
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
GOTOmsdos
铂金会员

C++启程者


积分 5154
发帖 1827
注册 2003-7-18
状态 离线
『第 12 楼』:  

:info1,:text1,:exec1, :bat1是多了两句一样的,但要改还是再加GOTO,也差不多,而且可读性就弱一点了.发现EXEC和BAT是一样的,这要精简一下
:dir2,:flist2,:pkdir2 各自两句,实际上就是一句 %GET%加1再各自去:dir1,:flist1,:pkdir1这是没法再减了..因为后面是GOTO,硬要改反而复杂化了..
子BAT中的@ECHO OFF.  是这样,当时测试时,可能是单独BAT测的 ,结果把DIR 目录,等等也弄到了文件中,所以就加上了
现在你一提醒,已经有主BAT了,就不再需要@ECHO OFF了
至于标签后的数字,当时没有精简时,数字就是表示目录层数的,现在不需要层数了,自然可以去掉的...
另,由于第一层是根目录,跟后面的子目录,执行过程是不一样的,所以没法精简掉..后面就是只用一层子目录的过程进行递增递减的...
小改一下再贴出来...

[此贴子已经被作者于2005-4-29 20:06:40编辑过]




2005-4-29 00:00
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
GOTOmsdos
铂金会员

C++启程者


积分 5154
发帖 1827
注册 2003-7-18
状态 离线
『第 13 楼』:  

改好了
刚才在纯DOS下试了不在子BAT中加@ECHO OFF,但是,结果确实仍然输出了命令行本身,把它定向到了文件,这就不对了.
结果,还是加上去了,就没问题了..
改后如下:
@echo off
goto begin
:dirbars "上一级—→"[x]
[退  出]
[预  选]
[看文件]
[看目录]
:
:filebars "   上一级—→"[x]
[退  出]
[运行批处理文件]
[运行可执行文件]
[编辑文本文件]
[查看文件信息]
:
:begin
if exist drive.txt goto drive
wbat cls ! box "没有驱动器!" 退出
goto end
:drive
call w.bat list drive.txt
if errorlevel 100 goto end
:putdisk
if not exist notready.nst goto init1
find /i "%wbat%" notready.nst>nul
if errorlevel 1 goto init1
wbat box "您还没有在%wbat%盘放入盘片!" 重试
call diskfind
goto putdisk
:init1
set get=1
set dir%get%=%wbat%
:dirb
wbat box @%0:dirbars
if errorlevel 100 goto sub1
if errorlevel 4 goto dir
if errorlevel 3 goto file
if errorlevel 2 goto pick
goto end
:dir
if %get%==0 goto drive
if %get%==1 goto rootdir
echo @echo off>nestvar.bat
echo dir "%%dir%get%%%" /b/ad/one>>nestvar.bat
command /c call nestvar>put.nst
goto subdir
:rootdir
dir %dir1%\ /b/ad/one>put.nst
:subdir
get f put.nst /vfsize>nul
if not "%fsize%"=="0" goto havedir
wbat box "没有子目录!" 上一级,退出
if errorlevel 2 goto end
goto dirb
:havedir
call w.bat list put.nst
if errorlevel 100 goto dirb
get r "+" %get% /w1 /vgetadd1>nul
echo @echo off>nestvar.bat
echo set dir%getadd1%=%%dir%get%%%\%wbat%>>nestvar.bat
call nestvar
wbat box @%0:dirbars
if errorlevel 100 goto havedir
if errorlevel 4 goto diradd1
if errorlevel 3 goto fileadd1
if errorlevel 2 goto pickadd1
goto end
:file
if %get%==1 goto rootfile
echo @echo off>nestvar.bat
echo dir "%%dir%get%%%" /b/a-d/one>>nestvar.bat
command /c call nestvar>put.nst
goto subfile
:rootfile
dir %dir1%\ /b/a-d/one>put.nst
:subfile
get f put.nst /vfsize>nul
if not "%fsize%"=="0" goto havefile
wbat box "没有文件!" 上一级,退出
if errorlevel 2 goto end
goto dirb
:havefile
call w.bat list put.nst
if errorlevel 100 goto dirb
:fileb
wbat box @%0:filebars
if errorlevel 100 goto havefile
if errorlevel 5 goto info
if errorlevel 4 goto text
if errorlevel 3 goto exec-bat
if errorlevel 2 goto exec-bat
goto end
:info
echo @echo off>nestvar.bat
echo dir "%%dir%get%%%\%wbat%" /a>>nestvar.bat
command /c call nestvar>putfile.nst
wbat list putfile.nst
goto fileb
:text
echo @echo off>nestvar.bat
echo edit "%%dir%get%%%\%wbat%">>nestvar.bat
call nestvar
goto fileb
:exec-bat
echo @echo off>nestvar.bat
echo "%%dir%get%%%\%wbat%">>nestvar.bat
call nestvar
goto fileb
:pick
echo @echo off>nestvar.bat
echo set gamesave=%%dir%get%%%>>nestvar.bat
call nestvar
goto end
:sub1
get r "-" %get% /w1>nul
goto dir
:diradd1
get r "+" %get% /w1>nul
goto dir
:fileadd1
get r "+" %get% /w1>nul
goto file
:pickadd1
get r "+" %get% /w1>nul
goto pick
:end
for %%a in (nestvar.bat put.nst putfile.nst) do if exist %%a del %%a

[此贴子已经被作者于2005-4-29 20:14:58编辑过]




2005-4-29 00:00
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
willsort
元老会员

Batchinger


积分 4432
发帖 1512
注册 2002-10-18
状态 离线
『第 14 楼』:  

Re GOTOmsdos:  请告知你测试的纯DOS的版本,我在MS-DOS6.22和MS-DOS7.10中测试,未遇到此问题。



※ Batchinger 致 Bat Fans:请访问 [讨论]批处理编程的异类 ,欢迎交流与共享批处理编程心得!
2005-4-29 00:00
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
GOTOmsdos
铂金会员

C++启程者


积分 5154
发帖 1827
注册 2003-7-18
状态 离线
『第 15 楼』:  

就是在WENGIER的MSDOS7.10啊,而且几乎没加载什么TSR哦,更没用SHELL= 来改变COMMAND 很普通的环境.

2005-4-29 00:00
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
« [1] [2] »
请注意:您目前尚未注册或登录,请您注册登录以使用论坛的各项功能,例如发表和回复帖子等。


可打印版本 | 推荐给朋友 | 订阅主题 | 收藏主题



论坛跳转: