中国DOS联盟论坛

中国DOS联盟

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

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

游客:  注册 | 登录 | 命令行 | 会员 | 搜索 | 上传 | 帮助 »
中国DOS联盟论坛 » DOS批处理 & 脚本技术(批处理室) » [原创]*****FOR·语句·学习·指南*****
« [1] [2] [3] »
作者:
标题: [原创]*****FOR·语句·学习·指南***** 取消高亮 | 上一主题 | 下一主题
ansipeter
中级用户

替身



积分 269
发帖 130
注册 2007-3-23
状态 离线
『楼 主』:  [原创]*****FOR·语句·学习·指南*****

由于最近时间比较紧张,这篇文章是我这两天写的,有错误的地方希望大家见谅!也真心的希望大家能够全面掌握FOR语句的使用要领....

看到DOS联盟中的回帖后,有些人急于想学习FOR语句,有些人对于俺要写这篇原本资料已经满天飞的关于FOR语句的文章还抱有一定的怀疑

态度,这样看来还是写写为好,一是让高手们指点指点,二是顺便温习一下所学!声明一下,以下语句如果用%?形式全部在CMD命令提示符下运

行,用%%?形式是在批处理条件下运行!

1.FOR 语句
for %a in (****) do @echo %a  这种形式的FOR语句是最为简单的一种,没有/D /R /F等参数开关,用法也很普通,下面给大家简单介绍一下



C:\>for %a in (aa.txt bb.txt cc.txt) do @echo %a
运行结果如下:
aa.txt
bb.txt
cc.txt

当然了,我们使用通配符也是可以的
for %a in (*) do @echo %a
for %a in (a?*.txt) do @echo %a
等等一些方法都是大同小异。

用FOR语句可以简化运行命令的重复性,在一定程度上提高了运行速度,减少了代码量。

for %a in (*.cmd *.txt) do @echo %a

显示当前目录下所有后缀名为.CMD 和.TXT的文件,这对处理多个文件提供了方便。

当然我们也可以这样用它,以%PATH%环境变量为例,如下:

for %a in ("%path:;=" "%") do @echo %~a

运行结果如下:

C:\WINDOWS\system32
C:\WINDOWS
C:\WINDOWS\System32\Wbem

目的就是把PATH环境变量的每个路径分离出来进行逐行显示

2.FOR /D 语句

打开CMD命令提示符,在传说中的黑色框中输入如下语句:

C:\>for /d %a IN (*) do @echo %a

9527
ccp
Documents and Settings
ppw
Program Files
RavBin
WINDOWS
WINNT

结果如上,显示当前目录下各个目录名称,不包括文件名,对于 (*)--括号中的内容我们称之为"集", 其实我们也可以用(*.*)形式运行,意

思是指全部内容,其实它就是我们熟悉的通配符,而我理解的/D的作用跟过滤效果差不多(/D-DIRECTORY的缩写)就是只显示目录名!

同样的,我们运行如下语句:

C:\>for /d %a in (w*) do @echo %a
结果如下:

WINDOWS
WINNT

这条语句就是显示以W开头的目录名称!(不区分大小写)

C:\>for /d %a in (w*s) do @echo %a
WINDOWS

不用我说了吧,这跟通配符的用法有关。

我们在说说用?作为通配符使用在/D参数上

C:\>for /d %a in (w?nnt) do @echo %a---成功执行,不用说有WINNT目录,如果执行不成功表示没有此目录
WINNT

C:\>for /d %a in (w??nnt) do @echo %a--不成功,由于通配符的特性,只能匹配像WIINNT这样的目录

C:\>for /d %a in (w?nnt?) do @echo %a--成功,也有两个??为何成功,因为最后结尾处是?通配符,可以匹配如winnt winntt样式的目录
WINNT

好了,不说通配符的事情了,继续...


3.FOR /R  语句

本人理解/R这个R是recursive的缩写,也就是递归的意思。

递归嘛,就是对其目录及其子目录的所有文件进行操作,这全部归功于/R这个参数,下面我们举例说明一下用法:

for /r %a in (*) do @echo %a  同 for /r . %a in (*) do @echo %a 效果是一样的,不指定或者用.表示当前目录

此句的作用是显示当前目录及其子目录下的所有文件,当然也可以指定我们要操作的目录。

for /r d:\ansi %a in (*.txt) do @echo %a 

显示D:\ANSI目录及其子目录下所有的.TXT的文件名称

如果我们指定的目录名含有空格可以使用双引号来解决。

for /r "c:\program files" %a in (ok.*) do @echo %a

这样我们就可以显示c:\program files目录及其子目录下文件名为OK的所有文件。

虽然FOR /R 语句官方帮助提到如果集的内容为一个.点,可以列举该目录树,但我总觉得不爽,有的时候为了美观没有必要偷懒,其实列举目

录树我们可以用/D /R两个参数的联合使用来实现,如下:

for /d /r "c:\program files" %a in (*) do @echo %a---美观

for /r "c:\program files" %a in (.) do @echo %a ----感觉不爽


这样就可以列举c:\program files目录下所有目录及其子目录(不包括文件),把集设置为点号也未尝不可。


4.FOR /L 语句

FOR /L %%parameter IN (start,step,end) DO command 我们可以这样看待这个语句,这样便于大家理解。

for /l %a in (1,1,10) do @echo %a ------正序显示

for /l %a in (10,-1,0) do @echo %a------倒序显示

循环显示1-10这10个数字,我们可以随意修改这些数字,但是我们应该注意一些问题,如下:

(start,step,end)

step为正数时,end>=start
step为负数时,end<=start

当step为零时,情况如下:

start>end   运行无效
start<=end   无限循环

我们还需要知道这三个数字之间可以用其他分隔符,例如:

for /l %a in (1,1,10) do @echo %a
for /l %a in (1 1 10) do @echo %a
for /l %a in (1=1=10) do @echo %a
for /l %a in (1,1,10) do @echo %a
for /l %a in (1<tab>1<tab>10) do @echo %a

这五条语句运行的效果是一样的,<tab>---TAB键


5.FOR /F 语句

可算到了/F参数啦,很多新手对其掌握的不是太好,关键是要灵活应用就好,用多了就习惯了,习惯了就好了.....

首先我们要进行介绍的就是/F参数下的这几个选项:
   
   delims=xxx  以xxx作为FOR语句的分隔符,可以是多个符号或字符,默认值是一个空格
   skip=n        在文件开始跳过的行数。默认值是零,如果SKIP=X(X如果是0或者负数语句执行都会失败,因为零或负数根本就没有意义)
   eol=;         指一个行注释字符的结尾,默认指是分号(;)
      tokens=n      指每行准备要被替代的符合条件的标记,默认值是1
   usebackq      使用后引号进行FOR语句的处理。usebackq=use back quote(` `--属于后引号)

  我知道,对于一些FOR语句的帮助中在说明这几个选项的时候很多人对其描述的内容不是很清楚,以上说明其实也不是那么好理解,我只是

粗略介绍一下,想要真正理解这些选项的用途还要在实际应用中去体会,这样会更好的认识这些选项的含义。

  我会列举大量实例以便说明各个选项的用途:
  
  首先要让大家清楚/F在处理的时候有三种形式:

 FOR /F "选项" %? IN (文件名) DO command
 FOR /F "选项" %? IN ("字符串") DO command
 FOR /F "选项" %? IN ('命令') DO command   

1.我们首先要说DELIMS这个选项的一些应用

  ① for /f "delims==" %? in ('set') do @echo %?
     以等号作为分隔符处理SET命令运行的结果,显示所有的变量名称。

 ② 例如我们有ansi.txt文件,内容如下: 
  
  AAA BBB CCC
    DDD EEE BBB
    UUU LLL PPP
   
  for /f "delims=" %a in (ansi.txt) do @echo %a 我们没有给delims选项赋值,所以没有任何分隔符,就是显示文件的全部内容,包括

行首行尾有空格的情况。

2.TOKENS选项的一些应用
 
 ①我们还拿ansi.txt文件做测试
  
  for /f "tokens=2" %a in (ansi.txt) do @echo %a
   
|   AAA        |   BBB     |      CCC    |
    tokens=1      tokens=2      tokens=3

  默认以空格为分隔符,TOKENS=2取得第二个标记,所以以上这条语句取得了BBB EEE LLL 3个数值。

 ②for /f "tokens=*" %a in (ansi.txt) do @echo %a

  tokens=*取得所有标记,这种情况显示出来的结果会去掉行首前的空格,不会去掉行尾空格。
 例如:
 [      AAA BBB CCC      ]
  [ DDD DSDFDFDF     DDFDF  ]
  [VVSDF               S  ]
  
  []这个只是为了显示出空格的位置,执行以上语句结果如下:
 
 [AAA BBB CCC      ]
  [DDD DSDFDFDF     DDFDF  ]
  [VVSDF               S  ]

 ③for /f "tokens=1,3-5*" %a in ("A B C D E F G H") do @echo %a %b %c %d %e
   
              A       B       C        D        E         F       G        H
  tokens      1       2       3        4        5         6       7        8
              %a              %b       %c       %d        最后一个标记为*,所以从标记6往后的所有标记都赋值给 %e

 最后得到结果为: A C D E F G H

3.EOL选项
 
  很多人在用FOR语句的时候都不是太过注重这个EOL选项,其实它很烦人的

  我们都知道FOR语句中eol选项默认忽略是以分号(;)开头的行

  for /f "eol= delims=" %a in (" Hello World!") do @echo %a-----无任何显示,忽略了以空格开头的行

  for /f "delims= eol=" %a in (""Hello World!^") do @echo %a----无任何显示,忽略了以双引号开头的行


  两条语句虽然只是eol 和 delims选项掉换了位置但是意义却不同

  第一条eol在前,eol= 表示忽略以空格开头的行!!!

  第二条eol在选项里的最后一个,其实他会忽略以"双引号开头的行,是不是挺烦人的!
  
  由此看来,EOL选项不论是在哪个位置,他都是以等号后面的那个字符做为判断标准的

  那我们怎么来解决这个棘手的问题呢?

  我们可以用一些不常用的特殊字符或符号做为EOL的值,虽然不是很完美,但是一般情况应该可以应付啦!
  
    例如:for /f "eol=退格键 delims=" %%a in ("xxxxxxxxxxxx") do @echo.%%a
  
    其实对于解决一个问题来说最关键的是我们怎么去看待这个问题!

4.SKIP=n 选项
  
  这个选项其实没有什么好说的,大家也都知道,也没有什么特殊的用法,只不过注意几个问题就可以啦

  首先n的值不能是0或者负数,否则会报错!这也是合情合理的。

  for /f "skip=5" %a in (xxx.txt) @echo.%a
   
    跳过xxx.txt文件前5行,然后进行操作,当然我们也可以使用以下语句来实现:
   
    for /f "skip=00000000005" %a in (xxx.txt) @echo.%a  呵呵,只要0后面有数字效果一样,当然,如果你指定SKIP值大于文件本身的行
 
  数,那不会有任何显示啦!!!



5.USEBACKQ 使用后引号选项

  其实最初在学习FOR语句时我实在是不理解他帮助中所说的后引号到底有什么好处?也不理解他帮助中所讲的意思,我理解能力有问题。

  ①在集以后引号形式执行时必须用此选项
   
  for /f "usebackq delims==" %a in (`set`) do @echo %a
  
    ②当文件名中含有空格的时候可以使用USEBACKQ选项处理,这样很方便。

  for /f "usebackq tokens=*" %a in ("c:\hello world.txt") do @echo.%a

    在默认情况下FOR语句处理文件的时候是不能够加上双引号的,在以字符串的形式处理的时候才会使用双引号!
  
  如果我们使用如下语句就会出错: 
 
  for /f "tokens=*" %a in (c:\hello world.txt) do @echo.%a 

  因为他处理的对象是hello这个文件,而不是hello world.txt文件。这点我希望大家能够分辨清楚。

    ③那我们想用usebackq选项还要处理字符串该怎么办呢? 难道也使用双引号吗? 不,我们使用单引号

    for /f "usebackq delims=" %a in ('Hello Word!') do @echo.%a

    我看到国外有些网站说,如果字符串中含有双引号,可以使用usebackq来进行处理,也就是如下实例:

  for /f "usebackq delims=" %a in ('Hello "AnsiPeter" Word!') do @echo.%a

    其实正常语句也可以正常显示,用USEBACKQ选项可能便于区分吧,我是这样想的,如下:

  for /f "delims=" %a in ("Hello "AnsiPeter" Word!") do @echo.%a


   好了,基本上这几个选项说完了,下面我们来说说一些需要注意的问题:

 
  for /f "tokens=1,2,3 delims=. " %a in ("a.b.c d.e f") do @echo %a %b %c

  这是一条很普通的FOR语句

  执行结果是:a b c    delims选项是以空格和.作为分隔符的,如果改变成以下会是什么情况呢?

  for /f "tokens=1,2,3 delims= ." %a in ("a.b.c d.e f") do @echo %a %b %c

  报错,此时不应有 ."。这是为什么呢?

  我是这样理解的,FOR/F语句中的每个选项之间是以空格分开的,但除了eol选项,因为eol选项是以等号后面的字符做为判断标准的,不管
  EOL在选项的那个位置都是一样的,上面我们已经介绍过了

  在如下:

  for /f "delims= . tokens=1,2,3" %a in ("a.b.c d.e f") do @echo %a %b %c

  报错,不用再说了吧,他默认把.作为FOR语句/F其中的一个选项,但根本就不包括这个选项当然要报错了,在如下:


  for /f "delims=.  tokens=1,2,3" %%a in ("a.b.c d.e f") do @echo %a %b %c

  在这句.后面是两个空格,执行结果呢?如下:

  结果:a b c d

  这说明根本没有把空格当作分隔符号,如果当成分隔符号结果应该是:a b c才对

  又如下:

  for /f "delims= tokens=1,2,3" %%a in (" hello world ansi") do @echo %%a
  显示结果:hello world ansi

  for /f "tokens=1,2,3 delims= " %%a in (" hello world ansi") do @echo %%a
  显示结果:hello

  delims后面同样是空格,为什么有区别呢?

  第一条语句是没有赋给delims任何值的,不管他后面有多少空格也是一样,也就是没有任何分隔符,所以全部显示

  第二条语句因为delims选项是最后一个,他们是以双引号为结束标识符的,所以是以空格为分隔符的,所以我们现在还无法以把双引号做为
  delims选项的值。

   

[ Last edited by ansipeter on 2008-3-12 at 12:23 PM ]

   此帖被 +23 点积分       点击查看详情   
评分人:【 lxmxn 分数: +20  时间:2008-3-11 22:02
评分人:【 clonecd 分数: +2  时间:2008-3-13 15:43
评分人:【 batch 分数: +1  时间:2008-7-29 18:40




*讨厌的9527*  
2008-3-11 18:29
查看资料  发短消息 网志   编辑帖子  回复  引用回复
chenall
银牌会员




积分 1276
发帖 469
注册 2002-12-23
来自 福建泉州
状态 离线
『第 2 楼』:  

写得很详细,不错,支持楼主。



QQ:366840202
http://chenall.net
2008-3-11 20:42
查看资料  发送邮件  访问主页  发短消息 网志  OICQ (366840202)  编辑帖子  回复  引用回复
lxmxn
版主




积分 11386
发帖 4938
注册 2006-7-23
状态 离线
『第 3 楼』:  

for %a in ("%path:;=" "%") do @echo %~a

这句最经典!

以前总是用sed来分离路径(echo %path% | sed "s/;/\n/"),今天见识了,学习之。

2008-3-11 22:02
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
hnfeng
初级用户





积分 89
发帖 36
注册 2007-12-20
状态 离线
『第 4 楼』:  

学习了,谢谢分享,辛苦辛苦

2008-3-11 23:01
查看资料  发短消息 网志   编辑帖子  回复  引用回复
dddddd6
新手上路





积分 10
发帖 5
注册 2008-3-11
状态 离线
『第 5 楼』:  

好啊,这个我找了好久啊,拜谢

2008-3-11 23:38
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
jswait
新手上路





积分 8
发帖 4
注册 2008-3-23
状态 离线
『第 6 楼』:  

dos命令 – for

2008-3-23 20:44
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
xuwm1985
初级用户





积分 27
发帖 25
注册 2008-3-17
状态 离线
『第 7 楼』:  

good xuexi le

2008-3-24 12:18
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
MiniTiger
新手上路




积分 8
发帖 5
注册 2008-1-30
状态 离线
『第 8 楼』:  

先顶下 然后慢慢学习 谢谢楼主

2008-3-24 12:56
查看资料  发短消息 网志   编辑帖子  回复  引用回复
chd611
新手上路





积分 16
发帖 8
注册 2007-3-29
状态 离线
『第 9 楼』:  

真的很经典,,至少,我还看的懂,感觉,咽,很好,,收藏了。。

2008-4-9 19:35
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
kongshny
新手上路





积分 4
发帖 2
注册 2008-4-10
状态 离线
『第 10 楼』:  

写的很好!

2008-4-10 12:40
查看资料  发短消息 网志   编辑帖子  回复  引用回复
wqh
新手上路





积分 14
发帖 6
注册 2008-4-10
状态 离线
『第 11 楼』:  



  Quote:
Originally posted by lxmxn at 2008-3-11 10:02 PM:
for %a in ("%path:;=" "%") do @echo %~a

这句最经典!

以前总是用sed来分离路径(echo %path% | sed "s/;/\n/"),今天见识了,学习之。

粗体部分看不懂版主给解释一下吧,可以不

[ Last edited by wqh on 2008-4-10 at 05:14 PM ]

2008-4-10 17:06
查看资料  发短消息 网志   编辑帖子  回复  引用回复
itolaiai
初级用户





积分 25
发帖 11
注册 2007-5-18
状态 离线
『第 12 楼』:  

不错..

2008-4-11 08:52
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
chmsqsmy
新手上路





积分 16
发帖 8
注册 2008-4-11
状态 离线
『第 13 楼』:  

学习,DOS真是久违了

2008-4-11 10:34
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
ThinKing
中级用户





积分 471
发帖 207
注册 2007-5-3
状态 离线
『第 14 楼』:  



  Quote:
Originally posted by wqh at 2008-4-10 05:06 PM:


粗体部分看不懂版主给解释一下吧,可以不

[ Last edited by wqh on 2008-4-10 at 05:14 PM ]

在命令行试试下面这个命令就知道原因了:
echo ("%path:;=" "%")


2008-4-13 17:39
查看资料  发短消息 网志   编辑帖子  回复  引用回复
itolaiai
初级用户





积分 25
发帖 11
注册 2007-5-18
状态 离线
『第 15 楼』:  

顶起..l回头看..

   此帖被 +1 点积分    点击查看详情   
评分人:【 xyzzhu 分数: +1  时间:2008-7-26 07:46


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


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



论坛跳转: