回复 22# fanfande
详见《[系列教程]批处理for语句从入门到精通[20101225更新]》:http://bbs.bathome.net/thread-2189-1-1.html
tokens 是以 delims 指定的字符集为分隔符,对输入的单行或多行内容进行划分,并取在 tokens 中指定的第 n 节,而其后引用的参数则收 tokens 影响,如果要用令牌(%%a、%%b 等)对指定的某几节进行选取,必须在 tokens 中声明改节位置。
比如:- for /f %%a in ("测试 test") do echo %%%%a=%%a %%%%b=%%b
- ::在for 中除了 usebackq 和 skip 外所有开关均有默认参数,上面这句貌似啥也没设置,其实默认为:"eol=; tokens=1 delims=[tab制表符][空格]"
- ::而因为在隐藏的默认参数中,tokens 仅指定了 1,所以只分配第一节内容给了 %%a,而没有分配任何内容给 %%b
-
- for /f "tokens=1,2,4-5 delims=诗《》:" %%a in ("唐诗经典:(插入广告)《长恨歌》白居易") do echo 由 %%a 代诗人 %%d 所著的 %%c 是一部 %%b 。
- ::delims 指定了四个分隔符,tokens 以此为据,指定要取第1、2、4、5 节
- ::这里的 1,2 表示第 1 和 2 节,而 4-5 表示 4 到 5 节(在取连续多节的时候是很有效的简写,此处仅为示例)
- ::而要注意的是,因为此处未在 tokens 中指定第 3 节,故 %%c 跳过第三节,直接与已被声明的第 4 节对应,%%d 则紧随其后,与第 5 节对应。
-
- for /f "tokens=2* delims=-" %%a in ("当前日期-北京时间-2011-11-24") do echo %%b
- ::tokens 中 * 除非是唯一参数,否则必须跟在某个数字后面,以声明其位置。
- ::在 tokens 中指定了某一节后我们可以不引用它,但是他会占用一个对应位置的令牌
-
- for /f "tokens=* delims=0" %%a in ("000001234000") do echo %%a
- ::将第一节与其后内容作为一个整体,去掉前缀的所有分隔符 0
- ::"tokens=*" 与 "delims=" 的区别就在于此,前者将删除第一节之前的所有分隔符取其后内容,而后者则是不指定分隔符所以整行文本作为一节内容输出。
复制代码 需要注意的是,tokens 的范围从 1~32,其中能明确指定第几节的是 1~31 节,第 32 个只能是 *,无法一次性取得。
我们写在 in 前面的那个令牌代表所取的第一节,其后令牌往下类推,比如当第一个令牌为 %%a 时,第 2-3 节为 %%b 和 %%c,当第一个令牌被设为 %%b 时,第 2-3 节为 %%c 和 %%d,依此类推,不过大小写字母是不同的,原因见下文。
当然可能有人会疑惑了,字母才 26 个,要怎么设定为首的令牌怎么取满 1-31* 中所有节呢?其实这不成问题,因为 for 中的令牌名是以 unicode 编码形式出现的,unicode 编码顺序就是令牌的排序,而几乎所有 unicode 字符均可作为令牌名
在 hanyeguxing 的 《Windows 代码页与字符顺序》:http://bbs.bathome.net/viewthread.php?tid=12329 中声明:
第二类如 set 、dir 、for 等,按 UNICODE 编码顺序排列,不使用 sortkey.nls 顺序。
而 plp626 的 《[讨论]批处理for命令的参数和扩展特性》:http://bbs.bathome.net/viewthread.php?tid=12500 中亦有实例证明:- :: cmd命令行下粘贴如下代码
- :: "老" 到 "耣" 的unicode编码(连续地)为 "8001" 到 "8023"
- 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
- for /f "tokens=1-31" %老 in ("%ss%")do @echo %老 %耂 %考 %耄 %者 %耆 %耇 %耈 %耉 %耊 %耋 %而 %耍 %耎 %耏 %耐 %耑 %耒 %耓 %耔 %耕 %耖 %耗 %耘 %耙 %耚 %耛 %耜 %耝 %耞 %耟 %耠 %耡 %耢 %耣
复制代码 而在 0x20~0x7f 范围内(小于 0x7f 都是单字节字符,超过此范围就是由双字节组成的宽字符)究竟有哪些字符可用,我也做过相应测试,证明除了某些字符由于预处理的原因无法使用以外,其余所有字符均可作为令牌名出现。 |