找回密码
 注册
搜索
[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
查看: 16357|回复: 1

[原创] for /f 与 cmd /c 的 command 处理

[复制链接]
发表于 2023-5-21 13:59:23 | 显示全部楼层 |阅读模式
本帖最后由 buyiyang 于 2023-9-19 20:28 编辑

for语句有这么一种用法
  1. FOR /F ["options"] %variable IN ('command') DO command [command-parameters]
复制代码
但当单引号中的command有一些特殊符号时,要用^转义,比如常用的管道符:
  1. for /f "delims=" %i in ('dir /b ^| find "123"') do echo,%i
复制代码
还可以改为加上引号
  1. for /f "delims=" %i in ('"dir /b | find "123""') do echo,%i
复制代码
cmd /c也有类似情况。
  1. 如果指定了 /C 或 /K,则会将该开关之后的命令行的剩余部分作为一个命令行处理。
  2. 其中,会使用下列逻辑处理引号(")字符:

  3.     1.  如果符合下列所有条件,则会保留命令行上的引号字符:

  4.         - 不带 /S 开关
  5.         - 正好两个引号字符
  6.         - 在两个引号字符之间无任何特殊字符,特殊字符指下列字符: &<>()@^|
  7.         - 在两个引号字符之间至少有一个空格字符
  8.         - 在两个引号字符之间的字符串是某个可执行文件的名称。

  9.     2.  否则,老办法是看第一个字符是否是引号字符,如果是,则去掉首字符并删除命令行上最后一个引号,保留最后一个引号之后的所有文本。
复制代码
也就是说cmd 的 /c 或 /k 后的部分是作为命令行字符串处理的,其中还特殊处理了引号。
我认为for /f 中单引号的'command'也是如此,还需要处理一些特殊字符,需要在双引号内或者转义,作为普通字符读取。
据我的测试,cmd /c的command中|&^需要转义,for /f的'command'中&<>()^|,=需要转义。
举两个特殊的例子:
  1. cmd /c for /f "delims=" %i in ('dir /b ^^^| find "123"') do echo,%i
  2. for /f "delims=" %i in ('for /f "delims=" %i in ^('dir /b ^^^| find "123"'^) do echo,%i') do echo,%i
复制代码
这两个例子有组合、嵌套,所以第二个for /f 中的命令行的|需要进行两次转义。

前面提到了,cmd 的 /c 或 /k 后的引号会进行特殊处理,
  1. cmd /c "a  1.bat" "value1" "value2"
复制代码
像这种情况就会去掉首尾两个引号,导致出错,可以这样解决:
  1. cmd /c "a  1.bat" value1 value2
  2. cmd /c ""a  1.bat" value1" value2
  3. cmd /c ""a  1.bat" "value1" "value2""
  4. cmd /c ,"a  1.bat" "value1" "value2"
复制代码
参考前面的的帮助就能解决。
而 for /f 同样会以类似的逻辑去掉引号,应该这样解决:
  1. for /f %i in ('"a  1.bat" value1 value2') do echo,%i
  2. for /f %i in ('""a  1.bat" "value1" "value2""') do echo,%i
复制代码
更新补充一下,
1、作为命令行字符串处理的部分实际上是开一个子程序,会再进行一次“预处理”(变量扩展和处理特殊字符),和大家比较常用的call echo %%a%%实现变量嵌套一样,结果是c。
  1. set a=b
  2. set b=c
  3. for /f %%i in ('echo %%a%%') do echo,%%i
复制代码
2、在输出文本时,for /f "delims=" %%i in ("1.txt") do echo,%%i无法输出空行,实际上,for语句执行do语句的依据就是索引变量%%i,
当索引变量为空时就不会执行do语句,在批处理用for /f从wmic的结果中正确取值中有对这一特性的运用,
  1. for /f "tokens=2" %%i in ('wmic process where "Name='WMIC.exe'" get Caption^,ExecutablePath') do set "p=%%i"
  2. echo %p%
复制代码
某些行只有一个多余的回车字符,当行只有一个字段时,而%%i被赋的值是第二个字段,为空,所以该轮循环的do不会执行,这样回车字符就被过滤了。

评分

参与人数 1技术 +1 收起 理由
77七 + 1 感谢分享

查看全部评分

发表于 2023-5-21 14:52:27 | 显示全部楼层
感谢大佬分享!
以前也见过why大佬分享过这个知识。
http://bbs.bathome.net/redirect. ... 5146&pid=264491
您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|手机版|小黑屋|批处理之家 ( 渝ICP备10000708号 )

GMT+8, 2026-3-17 05:45 , Processed in 0.021947 second(s), 12 queries , File On.

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表