Board logo

标题: 【练习-045】批处理按要求输出字符串并替换字符串 [打印本页]

作者: batman    时间: 2009-4-22 20:26     标题: 【练习-045】批处理按要求输出字符串并替换字符串

&&为了加强大家对大小写字母处理的技术,特出题,题目如下;
题一
   已知有abdefg kmli socsd pdxy nq五个字符串,要求用批处理随机输出大小写字符串到a.txt,,输出为每行10个字符串,共10
行,示例如下:
nqpdxySOCSDabdefgabdefgnqPDXYnqnqnq
pdxypdxyNQNQSOCSDSOCSDABDEFGKMLIkmlipdxy
socsdsocsdsocsdPDXYABDEFGabdefgPDXYnqsocsdPDXY
KMLIPDXYpdxySOCSDNQSOCSDABDEFGkmliNQABDEFG
SOCSDabdefgSOCSDabdefgPDXYnqKMLISOCSDSOCSDNQ
KMLIkmliabdefgNQnqKMLInqABDEFGKMLIpdxy
kmlipdxykmlipdxynqABDEFGNQKMLIpdxypdxy
pdxynqKMLInqsocsdABDEFGsocsdpdxypdxyABDEFG
KMLIpdxynqSOCSDPDXYKMLIKMLIpdxySOCSDnq
socsdnqNQkmliKMLIpdxynqabdefgSOCSDSOCSD
题二
   要求用批处理对文本a.txt中的字符串进行替换并输出到b.txt,注意替换是区分大小写的,如将里面的ABDEFG全替换成bathome,
但abdfeg不被替换,以上面的文本为例,输出后b.txt的内容应如下:
nqpdxySOCSDabdefgabdefgnqPDXYnqnqnq
pdxypdxyNQNQSOCSDSOCSDbathomeKMLIkmlipdxy
socsdsocsdsocsdPDXYbathomeabdefgPDXYnqsocsdPDXY
KMLIPDXYpdxySOCSDNQSOCSDbathomekmliNQbathome
SOCSDabdefgSOCSDabdefgPDXYnqKMLISOCSDSOCSDNQ
KMLIkmliabdefgNQnqKMLInqbathomeKMLIpdxy
kmlipdxykmlipdxynqbathomeNQKMLIpdxypdxy
pdxynqKMLInqsocsdbathomesocsdpdxypdxybathome
KMLIpdxynqSOCSDPDXYKMLIKMLIpdxySOCSDnq
socsdnqNQkmliKMLIpdxynqabdefgSOCSDSOCSD
第一题满分10分,第二题满分20分,视情况加分,加分以思路为重
作者: 随风    时间: 2009-4-22 20:44

第二题太简单了吧。
作者: batman    时间: 2009-4-22 20:52

多谢随风兄指出,已修正。
作者: Batcher    时间: 2009-4-22 21:13

第二题
  1. @echo off
  2. mshta "javascript:var fso=new ActiveXObject('Scripting.FileSystemObject');fso.OpenTextFile('C:\\test\\b.txt',2,true).Write(fso.OpenTextFile('C:\\test\\a.txt').ReadAll().replace(/ABDEFG/g, 'bathome'));close()"
复制代码

作者: xxx    时间: 2009-4-22 21:18     标题: 回复 4楼 的帖子

调用vbs都行...vbs看起来比批处理明了直接多了.

我冲动了哈...

[ 本帖最后由 xxx 于 2009-4-22 21:38 编辑 ]
作者: Batcher    时间: 2009-4-22 21:22     标题: 回复 5楼 的帖子

那个...那个...嗯~~~好像不是VBS吧?
作者: xxx    时间: 2009-4-22 21:39     标题: 回复 6楼 的帖子

原来是js啊...脸红.
作者: batman    时间: 2009-4-22 21:45

请大家用纯批解决,虽然这个要求有点苛刻。。。
作者: batman    时间: 2009-4-22 21:58

楼上没想到直接set "var=abdefg ABDEFG kmli KMLI socsd SOCSD pdxy PDXY nq NQ"?
作者: rat    时间: 2009-4-22 23:10

题外话,居然还能将自己的帖子设置成高亮,这是Bug吧。
作者: Batcher    时间: 2009-4-22 23:14     标题: 回复 12楼 的帖子

论坛的默认设置版主应该可以操作包含自己的帖子在内的所有帖子吧,有些论坛不能这样做估计是后台做了客户化的设置。
作者: inittab    时间: 2009-4-22 23:53

第二题:

  1. @echo off&setlocal enabledelayedexpansion
  2. set replace=bathome
  3. for /f "delims=" %%a in (a.txt) do set n=0&set "st="&call :sub %%a
  4. pause>nul&goto :eof
  5. :sub
  6. set str0=%1&set str1=!str0:~%n%,6!
  7. if "!str1!"=="ABDEFG" (set st=!st!!replace!&set/a n+=6) else (set st=!st!!str0:~%n%,1!&set/a n+=1)
  8. if not "!str1!"=="" (goto sub)
  9. echo !st!
  10. goto :eof
复制代码

作者: inittab    时间: 2009-4-23 01:32

第一小题:
思路,用数字作为变量对应字串。将随机数转化为数字变量替换后输出随机字串。
  1. @echo off&setlocal enabledelayedexpansion
  2. set "var=abdefg ABDEFG kmli KMLI socsd SOCSD pdxy PDXY nq NQ"
  3. set n=0
  4. for %%i in (%var%) do (set !n!=%%i&set/a n+=1)
  5. :begin
  6. set ram=%random%%random%%random%&set "str="
  7. for /l %%a in (1,1,10) do (set "str=!str! !ram:~%%a,1! ")
  8. set out=%str: =!!%
  9. echo !out!>>b.txt
  10. set/a n-=1&if !n! gtr 0 (goto :begin)
  11. start b.txt
复制代码

[ 本帖最后由 inittab 于 2009-4-23 07:35 编辑 ]
作者: 随风    时间: 2009-4-23 01:44

第一题
  1. @echo off&setlocal enabledelayedexpansion
  2. set "var1=abdefg kmli socsd pdxy nq ABDEFG KMLI SOCSD PDXY NQ"
  3. for %%a in (!var1!) do (
  4.    set /a n+=1,m=n-5
  5.    if !n! leq 5 (set .!n!=%%a) else set "#!m!=%%a"
  6. )
  7. for /l %%l in (1 1 10) do (
  8.    set "num="
  9.    for /l %%a in (1 1 10) do (
  10.       set /a w=!random!%%2,y=!random!%%5+1
  11.       for %%j in (!y!) do if !w! equ 0 (set str=!#%%j!) else set str=!.%%j!
  12.       set num=!num!!str!
  13.    )
  14.    echo !num!
  15. )
  16. pause
复制代码
第二题还真是费了翻脑筋。。
  1. @echo off&setlocal enabledelayedexpansion
  2. set zm=a b c d e f g h i j k l m n o p q r s t u v w x y z
  3. set "var1=ABDEFG"
  4. set "var2=bathome"
  5. set "max=!var1!"
  6. for %%a in (!zm!) do set max=!max:%%a= %%a !
  7. for %%a in (!max!) do set /a n+=1
  8. for /f "delims=" %%a in (a.txt) do (
  9.     set num2=%%a&set "jie="
  10.     set num=!num2:%var1%= %var1% !
  11.     for %%i in (!num!) do (
  12.        if /i not "%%i"=="%var1%" (set jie=!jie!%%i) else (
  13.           set "str=!num2:~0,%n%!"
  14.           if "!str!"=="%var1%" (set jie=!jie!%var2%) else set "jie=!jie!!str!"
  15.         )
  16.         set "num2=!num2:*%%i=!"
  17.      )     
  18.     echo !jie!
  19. )
  20. pause
复制代码

[ 本帖最后由 随风 于 2009-4-23 06:07 编辑 ]
作者: 随风    时间: 2009-4-23 06:20     标题: 回复 15楼 的帖子

  1. 牛!
  2. set out=%str: =!!% 好晦涩的写法 不仅使我想起了 %var:*"=set "var=%
  3. 它们是兄弟吧 ^_^
  4. 百思不得其解 set out=%str: =!!% 这句是如何替换的?能讲解下吗?
  5. 你好像少写了个空格 (set "str=!str! !ram:~%%a,1! ") 否则第一个字符是数字。
复制代码
.

[ 本帖最后由 随风 于 2009-4-23 06:51 编辑 ]
作者: inittab    时间: 2009-4-23 07:35

原帖由 随风 于 2009-4-23 06:20 发表
牛!
set out=%str: =!!% 好晦涩的写法 不仅使我想起了 %var:*"=set "var=%
它们是兄弟吧 ^_^
百思不得其解 set out=%str: =!!% 这句是如何替换的?能讲解下吗?
你好像少写了个空格 (set "str=!str! !ram:~%%a ...


多谢指出。没注意的确少了个空格,
set out=%str: =!!% 这句是把数字变为变量。
如1 2 3 4 5 6替换为!!1!!2!!3!!4!!5!! 前边已把定义过1~0 为变量为10个字串了,所以输出就是它们的随机组合

学批处理还不到一月,还有很多东西要向各位老大学习
作者: 随风    时间: 2009-4-23 07:54     标题: 回复 18楼 的帖子

多谢,原来就是把空格替换为 !! 号啊,汗,想多了,反而把最基础的搞忘了。。。
这样也可以
  1. for /l %%a in (1,1,10) do (set "str=!str! ^!!ram:~%%a,1!^!")
  2. echo %str%
复制代码

[ 本帖最后由 随风 于 2009-4-23 08:01 编辑 ]
作者: zqz0012005    时间: 2009-4-23 11:06

第二题,终于能兼容特殊字符,还真是费了番脑筋
  1. @echo off
  2. set str=ABDEFG
  3. set dst=bathome
  4. for /f "delims=" %%i in ('findstr /n .* 12.txt') do (
  5.     set "var=%%i"
  6.     setlocal enabledelayedexpansion
  7.     set var=!var:*:=!
  8.     if defined var (
  9.         set var=!var!//巭//
  10.         set "result="
  11.         call :loop
  12.         echo !result:~,-5!
  13.     ) else echo.!var!
  14.     endlocal
  15. )
  16. pause&exit/b
  17. :loop
  18. set tail=!var:*%str%=!
  19. if "!tail!"=="!var!" (set result=!result!!tail!&goto :eof)
  20. rem set head=!var:%tail%=!
  21. rem 这里用%tail%会导致无法兼容特殊字符
  22. for /f "delims=" %%a in ("!tail!") do set head=!var:%%a=!
  23. rem 上面用for变量中介,虽然开启了变量延迟但即使变量tail中含有感叹号也不影响。
  24. set left=!head:%str%=!
  25. if "!left!%str%"=="!head!" (set result=!result!!left!%dst%) else set result=!result!!head!
  26. set var=!tail!
  27. goto loop
复制代码

作者: sjzong    时间: 2009-4-23 14:49     标题: 我也来试试

第二题代码如下:
  1. @echo off
  2. setlocal enabledelayedexpansion
  3. set/p var1=请输入要查找的内容:
  4. set/p var2=请输入要替换的内容:
  5. :len
  6. if not "!var1:~%num1%,1!"=="" (set/a num1+=1&goto :len)
  7. for /f "delims=" %%a in (a.txt) do (
  8. set str=%%a
  9. set/a num+=1
  10. call :replace !str! !num1!
  11. )
  12. pause
  13. goto :eof
  14. :replace
  15. set ss=%1
  16. set/a n=0
  17. :a
  18. set/a m=%n%+%2
  19. if not "!ss:~%n%,1!"=="" (
  20. if "!ss:~%n%,%2!"=="!var1!" (
  21. set ss=!ss:~0,%n%!!var2!!ss:~%m%!
  22. set/a n+=1
  23. goto :a
  24. ) else (set/a n+=1&goto:a)
  25. ) else (echo !ss!>>aa.txt)
复制代码

[ 本帖最后由 sjzong 于 2009-4-24 11:47 编辑 ]
作者: czq19731102    时间: 2009-4-23 15:11     标题: 第一题

  1. @echo off&setlocal enabledelayedexpansion
  2. cd.>test.txt
  3. set BIG=A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
  4. set a=1
  5. set b=1
  6. :for
  7. set /a n=%RANDOM%%%5
  8. set /a n+=1
  9. for /f "tokens=%n%" %%I in ("abdefg kmli socsd pdxy nq") do (set var=%%I)
  10. set /a m=%RANDOM%%%2
  11. if %m% EQU 1 (for %%i in (%BIG%) do (set var=!var:%%i=%%i!))
  12. set /p var=!var! <nul>>test.txt
  13. set /a a+=1
  14. if %a% GTR 10 (echo.>>test.txt&goto end) else goto for
  15. :end
  16. set /a b+=1
  17. if %b% GTR 10 (goto exit) else set a=1&goto for
  18. :exit
  19. exit
复制代码

[ 本帖最后由 czq19731102 于 2009-4-23 21:06 编辑 ]
作者: 随风    时间: 2009-4-23 15:28     标题: 回复 21楼 的帖子

ABDEFGABDEFGabdefgabdefgabdefgABDEFGABDEFGABDEFG
把这行放进去试试
作者: sjzong    时间: 2009-4-23 15:51     标题: 回 23楼 的帖子

对了,你说的我已经试过了,可以的!这边有个问题:就是我的这批处理中是已经知道a.txt有十行,所以,我这边直接if !num!==10 goto :b 用来判断是否结束!

如果你把你说的那一行放在a.txt的最后一行,就不能显示了,因为已经是十一行,所以就没有结果!

我还是改过来!用for语句来直接判断a.txt的行数了!!

[ 本帖最后由 sjzong 于 2009-4-23 15:56 编辑 ]
作者: batman    时间: 2009-4-23 16:22

我在题目中选取ABDEFG来做替换字符是只是为了举例,并不一定总是拿ABDEFG替换为
bathome,所以请大家在解答时还是要注意下代码的通用性,另不要考虑特殊字符。。。
作者: 随风    时间: 2009-4-23 17:31     标题: 回复 24楼 的帖子

你确定你21楼的代码可以?
a.txt 就一行内容
ABDEFGABDEFGabdefgabdefgabdefgABDEFGABDEFGABDEFG
把 ABDEFG 替换为 ------
结果如下:
------ABDEFGabdefgabdefgabdefg------ABDEFG------
作者: czq19731102    时间: 2009-4-23 22:51     标题: 回复 18楼 的帖子

哇!不到一月就这么厉害了啊!
好另类的思维模式啊!不看作者解说,还真没想到他是这么想的,学习了

[ 本帖最后由 czq19731102 于 2009-4-23 23:02 编辑 ]
作者: netbenton    时间: 2009-4-24 01:49

第一题:(加满分也不多,呵呵!)
  1. @echo off&setlocal enabledelayedexpansion
  2. set ``=%%
  3. set "str=abdefg ABDEFG kmli KMLI socsd SOCSD pdxy PDXY nq NQ"
  4. 1:>a.txt
  5. :lp
  6. set/a n+=1&set com=
  7. for /l %%a in (1,1,10) do (set/a r=!random!%%10&set "com=!com!!``!!r!")
  8. for /f "tokens=1-10" %%0 in ("%str%") do (echo.%com%>>a.txt)
  9. if %n% lss 10 goto :lp
  10. start a.txt
  11. pause
复制代码

[ 本帖最后由 netbenton 于 2009-4-24 01:50 编辑 ]
作者: netbenton    时间: 2009-4-24 03:15

第二题:(能处理特殊字符:><!%:;"都可以)
  1. @echo off
  2. set so=ABDEFG
  3. set de=bathome
  4. (for /f "tokens=*" %%a in (a.txt) do (
  5.         set str=%%a
  6.         setlocal enabledelayedexpansion
  7.         call :sub
  8.         endlocal
  9. ))>b.txt
  10. start b.txt
  11. pause
  12. goto :eof
  13. :sub
  14. set "cs=!str:*%so%=!"
  15. if "!cs!"=="!str!" (
  16.         if !str!==$$ set str=
  17.         if defined ok (echo !ok!!str!) else (echo !str!)
  18.         goto :eof
  19. )
  20. set "cr=!str:%so%%cs%=!"
  21. if not defined cs set cs=$$
  22. set "``=!str:%cs%=!"
  23. if not defined cr set cr=$$
  24. if "!``:%cr%=!"=="%so%" set ``=!``:%so%=%de%!
  25. set ok=!ok!!``!
  26. set str=!cs!
  27. goto :sub
复制代码

[ 本帖最后由 netbenton 于 2009-4-24 03:25 编辑 ]
作者: inittab    时间: 2009-4-24 06:22

netbenton兄的代码真是出神入化呀。在cn-dos 见识过您的功力
作者: inittab    时间: 2009-4-24 06:49     标题: 回复 28楼 的帖子

呵呵,多谢支持。
一月前我也还真不明白tokens delims是代表什么意思。刚好手头有一个任务要做。想了很多办法也没弄好。一不小心,百度到了cn-dos 及本坛。刚好坛上有个例子解决我的问题。但是看了各位老大的代码真是云里雾里的。于是我很强烈地想弄明白这些代码到底是怎么回事。学了几个有限的命令之后,越来越感到这些东西不断地在挑战我的脑细胞。
我觉得把自己的思路用p来实现是一件很爽很有成熟感的事情,我还有很多东西要学。
大家一起努力吧
作者: 随风    时间: 2009-4-24 07:08     标题: 回复 30楼 的帖子

29楼解的第一题与15楼思路相近,只是最后一个for没看明白,%%0这里必须是0才行,不知道为什么,不理解这个for的运作原理。
1:>a.txt 比 cd.>a.txt 只相差一个字符,却会出现错误提示,不知为何非要这样写?
难道是为了有意晦涩?

30楼 首先解题考虑不周,与21楼犯同样错误,
对 ABDEFGABDEFGabdefgabdefgabdefgABDEFGABDEFGABDEFG 字符串不能准确替换。
其次,效率不够高,也许是为了兼容特殊字符吧(未作详细测试)
总的来说效率还算过得去。
作者: zqz0012005    时间: 2009-4-24 09:17     标题: 回复 30楼 的帖子

看到有set "cr=!str:%so%%cs%=!"
使用了%cs%就注定无法完全兼容特殊字符。
试试加入一行:"ABDEFG"(带上引号)
作者: inittab    时间: 2009-4-24 09:22     标题: 回复 33楼 的帖子

29 30 楼这两段代码都看得很费力。
第一段觉得1:>a.txt 不要的可以。不清楚有什么用。是类似于type nul>a.txt ?
最后的for %%0 看明白了,是为配合com变量作显示。%com%值经上一步实际是
%%6%%4%%1%%2%%1%%8%%2%%3%%5%%7 所以前边必须用%%0作配合。
变成下边这样了。
for /f "tokens=1-10" %%0 in ("%str%") do (echo.%%6%%4%%1%%2%%1%%8%%2%%3%%5%%7)  思路跟我相近。

30楼的替换测试正常(特殊字符没测试)
ok ‘’两个变量最好初始化一下set "ok="&set "``=", 否则多次运行有变量残留。
思路是用变量层层替换法取出ABDEFG循环替换后输出,

!str:*a=! 此处*的作用很大。我是第一次学习到。
它的作用是只取str 中第一个匹配对象后边的字符。抛弃前边的字符
E:\bat>set aa=abcde
E:\bat>echo %aa:*c=%
de
E:\bat>echo %aa:c=%
abde
高手见笑了。还有个问题,就是如何才可以在最短时间内看明白代码的思路?
去掉@echo off ? 很乱哦。加echo !XX! &pause吗?。有好方法请指点一下。

[ 本帖最后由 inittab 于 2009-4-24 09:28 编辑 ]
作者: zqz0012005    时间: 2009-4-24 09:25     标题: 回复 33楼 的帖子

关于%%0可以看看此帖:
http://bbs.verybat.org/viewthread.php?tid=10871&page=1&highlight=for%B5%C4%B1%E4%C1%BF%C3%BB%D3%D0%B9%E6%B6%A8%B1%D8%D0%EB%CA%C7%D7%D6%C4%B8&fromuid=37#pid150103
作者: batman    时间: 2009-4-24 11:34

看来大家都很积极,这确实是一个好现象,现给出本人第一题的解(第二题由于没有新思
路暂不公布):
  1. @echo off&setlocal enabledelayedexpansion
  2. cd.>a.txt
  3. set "str=abdefg kmli socsd pdxy nq ABDEFG KMLI SOCSD PDXY NQ"
  4. for /l %%a in (1,1,100) do (
  5.      set /a a=!random!%%10+1,b=%%a%%10&call :lp
  6.      if !b! equ 0 echo.>>a.txt
  7. )
  8. start a.txt&goto :eof
  9. :lp
  10. for /f "tokens=%a%" %%a in ("%str%") do set /p=%%a<nul>>a.txt
复制代码

[ 本帖最后由 batman 于 2009-4-24 11:37 编辑 ]
作者: netbenton    时间: 2009-4-24 12:54

1:>a.txt指在产生一个空文件,出错提示,不会有任何影响,
这个说明了1:是可以作为盘符的,如果存在。刚看了别人的多种产生临时文件的方法,所以就试一下,没别的什么意思。
ABDEFGABDEFGabdefgabdefgabdefgABDEFGABDEFGABDEFG
和“”
不能正确的问题确实没有考虑到。回头再想想,
作者: netbenton    时间: 2009-4-24 13:24     标题: 两个问题都解决了

用加尾巴,最后再丢弃,解决不能正确替换问题
用单个引号转为两个引号(用变量代入法才做到),最后再换回来。解决双引号错误问题
  1. @echo off
  2. set so=ABDEFG
  3. set de=bathome
  4. set @="
  5. set @@=""
  6. (for /f "tokens=*" %%a in (a.txt) do (
  7. set str=%%a#批处理#&setlocal enabledelayedexpansion
  8. set "str=!str:%@%=%@@%!"
  9. call :sub
  10. endlocal
  11. ))>b.txt
  12. start b.txt
  13. pause
  14. goto :eof
  15. :sub
  16. set "cs=!str:*%so%=!"
  17. if "!cs!"=="!str!" (
  18. set ok=!ok!!str!
  19. set "ok=!ok:%@@%=%@%!"
  20. echo !ok:~,-5!
  21. goto :eof
  22. )
  23. set "cr=!str:%so%%cs%=!"
  24. set "``=!str:%cs%=!"
  25. if defined cr set "``=!``:%cr%=!"
  26. if "!``!"=="%so%" set ``=%de%
  27. set ok=!ok!!cr!!``!
  28. set str=!cs!
  29. goto :sub
复制代码
这种方法,偶认为肯定比用findstr要高效。

[ 本帖最后由 netbenton 于 2009-4-24 13:54 编辑 ]
作者: 随风    时间: 2009-4-24 15:43     标题: 回复 36楼 的帖子

多谢zqz001205的链接,预处理一直是一道我无法迈入的门槛,看来看去总是晕晕沉沉的。
但此题我的疑问和预处理好像没什么太大关系,不过看帖的时候却突然灵光一现茅塞顿开。
我知道经过第一个for后com变成了%%6%%4%%1%%2%%1%%8%%2%%3 样字串,
只是没明白for /f "tokens=1-10" %%0 这里取 1-10 的用意,当然也就搞不清 %%0 的作用了。
原来如此简单。。。
汗! 一个主题帖中居然两次对初级问题犯迷糊,惭愧。。。

[ 本帖最后由 随风 于 2009-4-24 15:57 编辑 ]
作者: 随风    时间: 2009-4-24 16:14     标题: 回复 39楼 的帖子

特殊字符是cmd的软肋,无论怎么考虑都很难考虑周全,增加代码量不说对运行效率也有一定影响,
所以一般写bat代码通常不用兼容特殊字符(或是根据实际情况针对性的兼容),
当然若在不明显影响效率的情况下是兼容的越多越好
楼主之所以声明不用考虑特殊字符的原因我想应该也是如此吧
你39楼的代码,再给你下面两个字符串试试?看看都替换成了什么。
ABDEFG!%^@#!ABDEFG!abdefgabdefgabdefgABDEFG
ABDEFG!%^@#!ABDEFGabdefgabdefgabdefgABDEFG
作者: zqz0012005    时间: 2009-4-24 17:04     标题: 回复 40楼 的帖子

这样的用法虽然技术原理没有什么不同,但确有新意。
首先一般不易想到%%0是for的变量(帮助中提到的都是字母形式),如果不是以前对这种形式有所接触,刚见到它时我也觉得可能有问题。
其次是echo.%com%>>a.txt,并不是像echo %%0、%%1那样显式地出现for的变量,必要经过预处理,进行变量展开后才变成%6%4%1%2%1%8%2%3(注意不是%%而是%,因为变量``的值是%) 之类的字串。这样非显式出现使得%%0的作用更难弄清楚。而对于tokens=1-10,指定变量%0之后的变量引用是%1、%2等依次递增的数字(for的变量其实是%i的形式,bat中写成%%i是为了预处理),它们是隐式出现于%com%中。

在这个问题上犯迷糊很正常,没有相关水平连迷糊都犯不上(干脆不懂),实在是有新意。

[ 本帖最后由 zqz0012005 于 2009-4-24 17:07 编辑 ]
作者: batman    时间: 2009-4-24 18:17

对for中变量的用法,大家有兴趣的可以看看此贴的七楼这段代码(可别晕了哦)。。。。
http://bbs.bathome.net/viewthrea ... hlight=%C1%B7%CF%B0
作者: sjzong    时间: 2009-4-24 18:40     标题: 第一题

  1. @echo off
  2. setlocal enabledelayedexpansion
  3. set "var=abdefg ABDEFG kmli KMLI socsd SOCSD pdxy PDXY nq NQ"
  4. set/a n=0
  5. for %%i in (%var%) do (set !n!=%%i&set/a n+=1)
  6. cd.>a.txt
  7. set/a m=0
  8. :a
  9. if !m! lss 10 (
  10. set/a n=0
  11. set str=
  12. :b
  13. set/a s=%random%%%10
  14. set str=!str!!%s%!
  15. if !n!==9 (
  16. echo !str!>>a.txt
  17. set/a m+=1
  18. goto :a) else (set/a n+=1&goto :b)
  19. )
  20. start a.txt
  21. pause
复制代码

[ 本帖最后由 sjzong 于 2009-4-25 00:10 编辑 ]
作者: 随风    时间: 2009-4-24 19:05     标题: 回复 42楼 的帖子

新意确实有,但这和预处理好像相关不大,
你说“echo.%com%>>a.txt,并不是像echo %%0、%%1那样显式地出现for的变量,必要经过预处理”
我不这么认为,其实预处理应该在set "com=!com!!``!!r!" 的时候就已经处理了,这应该也是
作者为什么要 set ``=两个%% 而不= 一个 % 号的原因吧。
我认为,其实 echo.%com%>>a.txt 就是和 echo %%0 %%1 %%2 %%3 ..... 是一样的,
只不过这里的数字不是按顺序排列的而是通过前面得到的随机数0-9 ,
而%%0 就是为了保证后面的   %%+数字 能够正确显示,
就象我们要  echo %%b 前面就要定义 %%a 是一个道理。
for 用数字作变量,一直都知道,但始终认为它容易和批处理的参数搞混,
所以个人一直不提倡这种用法,只是没想到在这里却发挥了它的独到作用。
15楼的也是如此。
作者: zqz0012005    时间: 2009-4-24 21:00

预处理并非一次性处理完毕,而是边执行边处理。
set "com=!com!!``!!r!"
这个语句基本上不需要“预处理”做什么,设置变量com是语句中的命令完成的。
set ``=%%
预处理时将两个%%号变成一个,然后才是set赋值,所以变量``的值是一个%
“我认为,其实 echo.%com%>>a.txt 就是和 echo %%0 %%1 %%2 %%3 ..... 是一样的”
在预处理之前,形式上明显不同。预处理后,前者是%6%4%1%...(预处理对变量com进行展开的结果),此时才出现%n(如果对com不赋予这样的值,就没有for变量%1、%2等,所以说是隐式的),后者直接是echo %1 %2 %3...。预处理后两者才是一样。

可能是大家对“预处理”这个词的理解不一样,但只要明白语句的执行方式,不管怎么理解都一样,毕竟没有官方说法。
作者: netbenton    时间: 2009-4-24 22:23     标题: re 随风

偶认为echo.%com%>>a.txt是预处理。
同一组数据里面只对%号进行一次替换和减半操作,(加call 后面算是组外的了)
而for 令牌,本来就是只用一个%号的,只要经预处理后形成合适的参数形式,for运行时就会进行取值替换。
如:set  `=%%
for /f "tokens=1,2,3" %%a in ("aa bb cc") do (echo %`%a %`%b %`%c)
一样能正确执行。

其实com的值是%0%1%3。。。而不是:%%0%%1%%3
可用set com查看就知道了。

谢谢测试,确实不能处理所有的特殊字符,君的方法好像处理格时也会出问题。

[ 本帖最后由 netbenton 于 2009-4-24 22:34 编辑 ]
作者: netbenton    时间: 2009-4-25 17:05

第一题,换种方法
  1. @echo off&setlocal enabledelayedexpansion
  2. set "sou=abdefg ABDEFG kmli KMLI socsd SOCSD pdxy PDXY nq NQ"
  3. (for %%a in (%sou%) do (
  4. set des=
  5. for %%b in (%sou%) do (
  6.   set str= %sou%
  7.   set/a a=!random!%%11
  8.   for /l %%c in (0,1,!a!) do (set str=!str:* =!)
  9.   for /f %%d in ("!str!") do set des=!des!%%d
  10. )
  11. echo !des!
  12. ))>a.txt
  13. start a.txt
  14. pause
复制代码

作者: curious    时间: 2009-4-28 08:19     标题: to 15楼

set ram=%random%%random%%random%&set "str="
此ram难道一定就超过11位?
作者: inittab    时间: 2009-4-29 09:08

谢谢楼上指出.这是以前写的.我也是新手有考虑不周之处. 其实这句也是多余的.
修正如下
  1. @echo off&setlocal enabledelayedexpansion
  2. set "var=abdefg ABDEFG kmli KMLI socsd SOCSD pdxy PDXY nq NQ"
  3. set n=0
  4. for %%i in (%var%) do (set !n!=%%i&set/a n+=1)
  5. :begin
  6. set "str="
  7. for /l %%a in (1,1,10) do set/a ran=!random!%%10&set "str=!str! !ran! "
  8. set out=%str: =!!%
  9. echo !out!>>b.txt
  10. set/a n-=1&if !n! gtr 0 (goto :begin)
  11. start b.txt
复制代码

作者: keen    时间: 2009-6-11 22:18

第一题:
  1. @echo off&setlocal enabledelayedexpansion
  2. for %%a in (abdefg kmli socsd pdxy nq ABDEFG KMLI SOCSD PDXY NQ) do set /a n+=1&set !n!=%%a
  3. for /l %%b in (1 1 10) do (
  4.     for /l %%i in (1 1 10) do (
  5.         set /a num=!random!%%10+1
  6.             for %%j in (!num!) do set /p=!%%j!<nul
  7. )
  8. echo\
  9. )
  10. pause>nul
复制代码

作者: jackerloo2009    时间: 2009-6-13 21:52     标题: 第一题

  1. echo off
  2. :cc
  3. set ee=
  4. setlocal enabledelayedexpansion
  5. set "var=abdefg ABDEFG kmli KMLI socsd SOCSD pdxy PDXY nq NQ"
  6. set num=0
  7. :aa
  8. set /a num+=1
  9. set /a c=%random%%%10+0
  10. for /f "tokens=1-10 delims= " %%0 in ("%var%") do set "ff=%%%c%"
  11. if !num!==11 goto dd
  12. set "ee=!ee!!ff!"
  13. goto aa
  14. :dd
  15. set /a nm+=1
  16. echo !ee!>>a.txt
  17. if !nm!==10 goto mm
  18. goto cc
  19. :mm
  20. pause
复制代码

作者: keen    时间: 2009-6-13 22:22     标题: 回复 52楼 的帖子

楼上是否对自己的代码测试过?
作者: jackerloo2009    时间: 2009-6-14 03:13     标题: 楼上直接指点吧

我新手,写代码难免有问题的,你是感觉我哪些地方用的不对吗?
作者: jackerloo2009    时间: 2009-6-14 03:23     标题: 第二题

  1. @echo off
  2. setlocal enabledelayedexpansion
  3. for /f "delims=" %%i in (b.txt) do set "d=%%i" & call :treat
  4. pause>nul
  5. :treat
  6. set m=0
  7. set "y="
  8. :cc
  9. set "e=!d:~%m%,6!"
  10. set "x=!d:~%m%,1!"
  11. set /a m+=1
  12. if "!e!"=="ABDEFG" set /a m-=1 & call set "y=%%d:!d:~%m%,6!=bathome%%" & set /a m+=1
  13. if "!x!"=="" goto dd
  14. goto cc
  15. :dd
  16. if "!y!"=="" (echo !d!>>bb.txt) else echo !y!>>bb.txt
  17. goto :eof
复制代码

作者: jackerloo2009    时间: 2009-6-14 03:51     标题: 关于echo %com%的问题

http://bbs.bathome.net/viewthrea ... amp;page=1#pid29527
当我还是个新手的时候就测试过这个问题了,尽管现在我还是新手,可惜当时就一个人指点明白了我当时的疑惑

作为直接取值如echo %%1 %%2 %%3必须是双%

但是作为变量赋值后的调用,赋值必须是单%

还有一个问题是echo %com% 的双%,尽管开启了变量延迟setlocal enabledelayedexpansion,但是我测试发现echo !com!这样的方式是错误的,只能echo %com%,至于为什么还有待高手指点
作者: zhouyongjun    时间: 2009-6-15 09:27

  1. @echo off&setlocal enabledelayedexpansion
  2. for %%i in (abdefg kmli socsd pdxy nq ABDEFG KMLI SOCSD PDXY NQ) do (
  3.     set/a n+=1&set _!n!=%%i
  4. )
  5. (for /l %%a in (1,1,10) do (
  6.     for /l %%b in (1,1,10) do (
  7.         set/a num=!random!%%10+1
  8.         for %%c in (_!num!) do set/p=!%%c!<nul
  9.     )
  10.     echo/
  11. ))>a.txt
  12. (for /f "delims=" %%a in (a.txt) do (
  13.     set str=%%a&set var=!str:abdefg= abdefg !&set "cut="
  14.     for %%b in (!var!) do (
  15.         if /i "%%b" neq "abdefg" (
  16.             set/p=%%b<nul
  17.         ) else (
  18.             if defined cut call,set str=%%str:*!cut!=%%
  19.             if "!str:~,6!" equ "ABDEFG" (set/p=bathome<nul) else (set/p=%%b<nul)
  20.         )
  21.         set cut=%%b
  22.     )
  23.     echo/
  24. ))>b.txt
复制代码

作者: keen    时间: 2009-6-15 12:11     标题: 回复 54楼 的帖子

显示结果正确,代码中有些细节须注意,我给你的代码稍作改动,你可以跟你的52楼代码做一比较:
  1. @echo off&setlocal enabledelayedexpansion
  2. :cc
  3. set ee=
  4. set "var=abdefg ABDEFG kmli KMLI socsd SOCSD pdxy PDXY nq NQ"
  5. set num=0
  6. :aa
  7. set /a num+=1
  8. set /a c=%random%%%10
  9. for /f "tokens=1-10" %%0 in ("%var%") do set "ff=%%%c%"
  10. if %num%==11 goto dd
  11. set "ee=!ee!!ff!"
  12. goto aa
  13. :dd
  14. set /a nm+=1
  15. echo %ee%>>a.txt
  16. if %nm%==10 goto mm
  17. goto cc
  18. :mm
  19. start a.txt
  20. pause
复制代码


你55楼的代码结果不对吧

[ 本帖最后由 keen 于 2009-6-15 12:46 编辑 ]
作者: jackerloo2009    时间: 2009-6-15 16:24     标题: 回复 58楼 的帖子

感谢指正!为什么要省去"delims= "这个呢?恩,还有个概念我有些模糊,就是开启延迟的时候,如何区分用!!还是%%

55楼的我测试的时候,是指定的b.txt    最后生成的是bb.txt    ,应该改成a.txt  生成 b.txt就对了

我是新手还望能多多指点
作者: keen    时间: 2009-6-15 16:52     标题: 回复 59楼 的帖子

省去"delims= "是因为默认就是以空格为分割符,所以为了缩小代码量,在单独以空格为分隔符可以省略!

开启延迟的时候,到底改用!!还是%%,请参看http://www.bathome.net/viewthrea ... 4%C1%BF%D1%D3%B3%D9

55楼的代码结果,你应该再仔细对照查看替换前和替换后的文本内容,是否只是替换了ABDEFG。
作者: jackerloo2009    时间: 2009-6-15 17:00     标题: 回复 60楼 的帖子

当时测试是没问题的,今天才发现最后重复了最后一行,现在想了半天了,也没想明白原因,我再想想
作者: jackerloo2009    时间: 2009-6-15 18:11

给我的感觉好像for在处理文本的时候总是预读一行,到最后一行它仍然预读下一行,结果下一行是空的,它就终止,可是我这个代码到最后那个if仍然满足条件结果就又重新指定了一遍了,是不是这个原因?
作者: jackerloo2009    时间: 2009-6-17 13:14     标题: 重写了个思路,为什么会出空格?

请大家给看看,指点一下
  1. @echo off
  2. del b.txt
  3. setlocal enabledelayedexpansion
  4. set var=bathome
  5. for /f "delims=" %%i in (a.txt) do set "d=%%i" & call :treat
  6. pause>nul & goto :eof
  7. :treat
  8. set m=0
  9. :cc
  10. set "f=!d:~%m%,1!"
  11. set "e=!d:~%m%,6!"
  12. if "%f%"=="" echo.>>b.txt & goto :eof
  13. if "%e%"=="ABDEFG" (set/p=%var%<nul>>b.txt & set /a m+=5) else (set/p=%f%<nul>>b.txt)
  14. set /a m+=1
  15. goto cc
复制代码


已经找到原因了,这样就好了 set/p=%var%<nul>>b.txt& set  /a m+=5
但是不明白为什么要把set/p=%var%<nul>>b.txt&这个&前面的空格去了才是对了,我以前总以为什么空开就是对的。。。。
作者: 随风    时间: 2009-6-17 17:29

但是不明白为什么要把set/p=%var%<nul>>b.txt&这个&前面的空格去了才是对了,我以前总以为什么空开就是对的。。。。

set /p 后面的所有内容都是提示信息,并不是以<nul终止
测试下面代码便知,变量var的值是a.txt的第一行内容,而1234则为set/p 的提示信息,不在var的值中。
你的代码只是用空设备nul取代了a.txt而以,其他的都一样。
:
  1. @echo off
  2. set /p var=<a.txt 1234
  3. echo;
  4. echo 〔%var%〕
  5. pause
复制代码

又或者
  1. @echo off
  2. set /p var=abcd<a.txt 1234
  3. echo;
  4. echo %var%
  5. pause
复制代码

[ 本帖最后由 随风 于 2009-6-17 17:36 编辑 ]




欢迎光临 批处理之家 (http://www.bathome.net/) Powered by Discuz! 7.2