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

[讨论]批处理for命令的参数和扩展特性

本帖最后由 plp626 于 2011-6-14 19:25 编辑

引号也可作为for /f delims的分割符,只是由于大家思维定势忽略了:
http://bathome.net/thread-12395-1-2.html 6楼
  1. @echo off
  2. for /f tokens^=1*^ delims^=^" %%a in ("sd"z"vc") do echo %%b
  3. pause
复制代码
我对for的一些理解:
http://bathome.net/viewthread.ph ... romuid=353#pid80129 26楼
可以这样理解for的二次扩展特性:
for ~ cmd内部的一个类似call的子过程。。。
:FOR [/F | /R | /D |/L]  [option] %variable IN (<parameters>) DO ...

这个内部子过程有/l /r /d /f 四个开关,有共同的do in 关键字,一对括号;
有最多31个连续(以unicode编码存储)单字符名的内置变量,内置变量以%作为前缀标识;
(相对call,若不shift则为11个,分别为%0 %1 %2 。。。。 %9还有特别参数%*);
由于脚本中第一个%会被cmd预处理解析作为变量值开始扩展
所以要再用一个%对“%”转义(这点很像反斜杠\对自身的转义)

/f 开关有eol,skip,usebackq,delims,tokens,5个关键字,他们作为/f开关的 “第一个参数传递”

调用这个子过程的时候,参数分割符同call的参数分隔符(空格,制表符,逗号,分号,等号);

比如
  1. for /f "tokens=1-2 delims=:" %%a in ("abc:123") do echo %%a %%b
复制代码
我们把参数分割符空格改为;,=也可以正常解析:
  1. for=;/f=;;"tokens=1-2 delims=:";;%%a==in,,("abc:xy"),,=;do,=echo %%a %%b
复制代码
更新[2011-6-14]
内置变量名(统一以unicode编码存储)以%作为前缀标识,最多支持连续31个单字符;
  1. :: cmd命令行下粘贴如下代码
  2. :: "老" 到 "耣" 的unicode编码(连续地)为 "8001" 到 "8023"
  3. set ss=1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
  4. for /f "tokens=1-31" %老 in ("%ss%")do @echo %老 %耂 %考 %耄 %者 %耆 %耇 %耈 %耉 %耊 %耋 %而 %耍 %耎 %耏 %耐 %耑 %耒 %耓 %耔 %耕 %耖 %耗 %耘 %耙 %耚 %耛 %耜 %耝 %耞 %耟 %耠 %耡 %耢 %耣
复制代码
2

评分人数

但是有一点我没明白,for 中,^是怎么对空格进行转义的;

call中^为什么不行,为什么call会对字符的^加倍扩展一次。

TOP

楼上,很好!
  1. for /f eol^=^;tokens^=1-3delims^=+ %a in ("5678+678+78")do echo %a %b %c
复制代码
在for之前,我一直认为空格本身就不能通过^转义的;
为什么在for中就是例外?
原来,^对空格转义又是我理解上的“多虑”;
这样基本可以把for的参数分割符和call参数分割统一起来;
=========================
但是这里有一点未明:
既然tokens,deliims这些关键字作为/f开关的第一参数,为什么在引号内空格又不能省略?

TOP

又是思维定势:
原来空格一直都是我们的“多虑”
  1. for /f "eol=;tokens=1-3delims=+" %a in ("5678+678+78")do echo %a %b %c
复制代码

TOP

本帖最后由 plp626 于 2011-5-26 16:36 编辑

12# applba

如果从call参数分隔符的角度去理解for /f 的第一参数(skip,delims那些) 和第二参数列表(括号里面的那些)
便不难理解为什么('命令')在“命令”含有逗号时要转义,因为它被当做参数分隔符解析为空了,

当括号里面有|,&,<,>这些特殊符号时为什么要用^转义这个也不难理解了

试想下call:标签 /f 参数1 内置变量 in (参数列表) do 。。。
当这个标签后面所跟的参数列表中出现|,<>,&这些特殊符号时,它会把这些特殊符号后面的字符串作为命令或其他东西解析了,参数列表被截断,而使得括号不能匹配,do关键字找不到,于是for报错了;
=========================
解决此两问题的办法我们除了用^转义|<>&还有参数分隔符外,也可以用双引号来统一解决:

for /f "选项" %%a in ('命令')do 命令 ---->>  for /f "选项" %%a in ('"命令"')do 命令

TOP

看得心慌,19楼的代码真的看懂了么?

那个for.exe命令行输入
  1. for.exe a=b=c x;,y 5678"\"\""" ....
复制代码
然后再输入
  1. for.exe /f delims=+ tokens=1-3 %a in ("fdf""dfd\"\"")do ^^echo %a
复制代码
体会下;

另外,cmd对代码预处理后的结果就是
在cmd开启echo on 后在屏幕上显示的结果;这个界定适合脚本也适合命令行;

我们看预处理做了哪些工作,用echo on的方法就行了,再做“批处理物理实验”就绕弯路了;

TOP

45# powerbat


【选项部分的参数】如何改变一直没方法(对大多数人,但我不敢断言就一直没方法);

【括号里的参数】在循环体内改变,这样的例子 【不胜枚举】;
  1. for %%a in (1 2)do set loop=%%a&for /l %%b in (1 1 !loop!)do echo %%b
  2. Set loop=1 1 2
  3. for %%a in (1 1) do for /L %%b in (!loop!) do Set loop=626 1 627& ECHO %%b
复制代码
你这个C语言代码推测很容易被推翻。

TOP

45# powerbat


括号里的参数是for的入口的参数,它改变后,重新调用这个for接口就可被再次读取;
这也就可以说明为什么
  1. set x=0
  2. for %%a in (1 2 !x! !x!)do echo %%a&set x=y
复制代码
不能改变;而
  1. set x=0
  2. for %%z in (1 1)do for %%a in (1 2 !x! !x!)do echo %%a&set x=y
复制代码
却被改变的原因;
=============================================
对于选项部分的参数(不知道该怎么叫,大家理解就好)我也仅是靠现象猜测(仅是便于理解):

选项部分的参数直接和for接口函数功能相关联,但在预处理的时候就被读取固定下来;
只要是在这个预处理阶段读取的语句,不管这个语句怎么改变选项部分的参数
能改变的仅仅是参数的值,而非这个for接口的函数功能了;

TOP

55# powerbat


是这样:
  1. (
  2. for %%a in (1 2 !x! !x!)do echo %%a&set x=y
  3. for %%a in (1 2 !x! !x!)do echo %%a&set x=y
  4. )
复制代码

TOP

返回列表