[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
返回列表 发帖
不错,以前我也是惯性思维,没留神过。只知道

for /f .... ('命令') do 。。。
中若命令含有等号,逗号,时,要给等号,等号,分毫加^转义。。。我就想这个是cmd另启动的进程把命令作为参数列表再次传给cmd处理。。。

所以一直用for /f .... (' "命令" ') do 。。。省事多了,,没再深入,看来。。。
这个for 可以看做cmd的函数了,delims tokens 不过是它的参数列表。。。这样就容易理解=, 空格不被双引号括起来就得^转义传递参数了

TOP

各位大大能解释一下这句吗?
(for /f tokens^=2^,4^ delims^=^" %%a in (test.txt) do echo %%a,%%b,1)>2.txt
一般看到的都是
for /f "tokens=1,delims=" 变量 in(文件名) do echo 变量
但是在这里怎么多加了2个 ...
fengyun530 发表于 2011-5-22 11:03



我的理解是(马后炮...)习惯上为for /f命令的各种参数加引号是为了转义“=”、“ ”等会被误认为分隔符的参数内容,for /f可能只能接受一个参数,所以useback可以不加引号:
for /f useback %%a in ("te st.txt") do echo %%a
但是却不能与其他参数不使用"来直接联用,而且其他带=或其他有分隔符意义字符的参数若不用"或者^来转义就直接使用,运行时“tokens=1,4”会被cmd理解成“tokens 1 4”,这当然会出错,但是我们可以通过用^转义的方法来代替引号的作用,原理就像
“for /f %%a in ('dir /b^|sort') do echo %%a”
等同于
“for /f %%a in ('"dir /b|sort"') do echo %%a”
一样。

TOP

而且利用for /f的特性也可以实现变量延迟哦:
  1. @echo off
  2. (
  3. echo %random%
  4. for /f %%a in ('echo %%random%%') do echo %%a
  5. pause
  6. )
复制代码
这是for /f的运行机制决定的

TOP

本帖最后由 applba 于 2011-5-25 07:22 编辑

我觉得
引号有转义所有特殊字符(除%)的作用,大多数时候用来转义空格。
for /f后面的一串option,使用引号主要就是为了转义空格和等号,防止预处理时空格和等号作为分隔符分割多个组合的option。
这两个引号在for /f运行的时候会被丢掉,引号中的option在执行时被解释。

既然用双引号是为了转义空格等字符,自然使用^也是可以转义空格和其他特殊字符的。
一般来说只要转义了空格和等号,使用^和双引号效果是一样的。
当然双引号更简单,但是如果涉及到双引号本身做分隔符就必须使用^。

下面是测试,1.txt的内容
  1. abcde^fg^
  2. abcd"efg"
  3. abc^de"fg
  4. abc"de^fg
复制代码
  1. @echo off
  2. ::^做分隔符的两种写法
  3. echo "^做分隔符的写法1"
  4. for /f "tokens=1-3delims=^" %%i in (1.txt) do echo %%j
  5. echo "^做分隔符的写法2"
  6. for /f tokens^=1-3delims^=^^ %%i in (1.txt) do echo %%j
  7. ::"做分隔符的写法
  8. for /f tokens^=1-3delims^=^" %%i in (1.txt) do echo %%j
  9. ::下面的写法提示“命令语法不正确 ”
  10. ::for /f "tokens=1-3 delims="" %%i in (1.txt) do echo %%j
  11. ::"和^一起做分隔符
  12. for /f tokens^=1-3delims^=^"^^ %%i in (1.txt) do echo %%j
复制代码
有人弄出来%做分隔符的情形吗?
1

评分人数

    • namejm: 分析得非常深入PB + 10 技术 + 1

TOP

19# applba

以百分号为分隔符要考虑到预处理的因素:
... delims=%% ...

TOP

本帖最后由 techon 于 2011-5-25 23:27 编辑

转义字符的确有不少妙用

在某些命令中 几乎所有字符都可以被转义处理
  1. @echo off
  2. echo 123%%456%%789>1.txt
  3. echo 123"456"789>>1.txt
  4. echo 123^&456^&789>>1.txt
  5. for /f tokens^=1-3^,*delims^=^%%^&^"^2 %%i in (1.txt) do @echo ---%%i---%%j---%%k---%%l
  6. pause
复制代码
回车,手动换行被转义处理
  1. set a=101
  2. if "!a:~0,1!"=="0" (echo a0===0&if "!a:~1,1!"=="0" (echo a1===0&if "!a:~2,1!"=="0" (echo a2===0) ^
  3.                                                                                else echo a2===1) ^
  4.                                                else echo a1===1&if "!a:~2,1!"=="0" (echo a2===0) ^
  5.                                                                                else echo a2===1) ^
  6.                else echo a0===1&if "!a:~1,1!"=="0" (echo a1===0&if "!a:~2,1!"=="0" (echo a2===0) ^
  7.                                                                                else echo a2===1) ^
  8.                                                else echo a1===1&if "!a:~2,1!"=="0" (echo a2===0) ^
  9.                                                                                else echo a2===1
  10. rem 规范格式
  11. set a=110
  12. if "!a:~0,1!"=="0" (
  13.   echo a0===0
  14.   if "!a:~1,1!"=="0" (
  15.     echo a1===0
  16.     if "!a:~2,1!"=="0" (
  17.       echo a2===0
  18.     ) else (
  19.       echo a2===1
  20.     )
  21.   ) else (
  22.     echo a1===1
  23.     if "!a:~2,1!"=="0" (
  24.       echo a2===0
  25.     ) else (
  26.       echo a2===1
  27.     )
  28.   )
  29. ) else (
  30.   echo a0===1
  31.   if "!a:~1,1!"=="0" (
  32.     echo a1===0
  33.     if "!a:~2,1!"=="0" (
  34.       echo a2===0
  35.     ) else (
  36.       echo a2===1
  37.     )
  38.   ) else (
  39.     echo a1===1
  40.     if "!a:~2,1!"=="0" (
  41.       echo a2===0
  42.     ) else (
  43.       echo a2===1
  44.     )
  45.   )
  46. )
  47. pause&goto :EOF
复制代码
解释执行的脚本语言与编译语言还是有很大差别的。。。

TOP

回复 2# CrLf


    我对tokens 感觉理解有点乱啊
有创新,多创新;无创新,多模仿;无模仿,多坚持

TOP

回复 22# fanfande


    详见《[系列教程]批处理for语句从入门到精通[20101225更新]》:http://bbs.bathome.net/thread-2189-1-1.html
tokens 是以 delims 指定的字符集为分隔符,对输入的单行或多行内容进行划分,并取在 tokens 中指定的第 n 节,而其后引用的参数则收 tokens 影响,如果要用令牌(%%a、%%b 等)对指定的某几节进行选取,必须在 tokens 中声明改节位置。
    比如:
  1. for /f %%a in ("测试 test") do echo %%%%a=%%a   %%%%b=%%b
  2. ::在for 中除了 usebackq 和 skip 外所有开关均有默认参数,上面这句貌似啥也没设置,其实默认为:"eol=; tokens=1 delims=[tab制表符][空格]"
  3. ::而因为在隐藏的默认参数中,tokens 仅指定了 1,所以只分配第一节内容给了 %%a,而没有分配任何内容给 %%b
  4. for /f "tokens=1,2,4-5 delims=诗《》:" %%a in ("唐诗经典:(插入广告)《长恨歌》白居易") do echo 由 %%a 代诗人 %%d 所著的 %%c 是一部 %%b 。
  5. ::delims 指定了四个分隔符,tokens 以此为据,指定要取第1、2、4、5 节
  6. ::这里的 1,2 表示第 1 和 2 节,而 4-5 表示 4 到 5 节(在取连续多节的时候是很有效的简写,此处仅为示例)
  7. ::而要注意的是,因为此处未在 tokens 中指定第 3 节,故 %%c 跳过第三节,直接与已被声明的第 4 节对应,%%d 则紧随其后,与第 5 节对应。
  8. for /f "tokens=2* delims=-" %%a in ("当前日期-北京时间-2011-11-24") do echo %%b
  9. ::tokens 中 * 除非是唯一参数,否则必须跟在某个数字后面,以声明其位置。
  10. ::在 tokens 中指定了某一节后我们可以不引用它,但是他会占用一个对应位置的令牌
  11. for /f "tokens=* delims=0" %%a in ("000001234000") do echo %%a
  12. ::将第一节与其后内容作为一个整体,去掉前缀的所有分隔符 0
  13. ::"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 中亦有实例证明:
  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 %老 %耂 %考 %耄 %者 %耆 %耇 %耈 %耉 %耊 %耋 %而 %耍 %耎 %耏 %耐 %耑 %耒 %耓 %耔 %耕 %耖 %耗 %耘 %耙 %耚 %耛 %耜 %耝 %耞 %耟 %耠 %耡 %耢 %耣
复制代码
而在 0x20~0x7f 范围内(小于 0x7f 都是单字节字符,超过此范围就是由双字节组成的宽字符)究竟有哪些字符可用,我也做过相应测试,证明除了某些字符由于预处理的原因无法使用以外,其余所有字符均可作为令牌名出现。

TOP

回复 6# CrLf


    太牛逼了
民工一枚

TOP

返回列表