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

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

本帖最后由 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

评分人数

    • 77七: 感谢分享技术 + 1

感谢大佬分享!
以前也见过why大佬分享过这个知识。
http://bbs.bathome.net/redirect. ... 5146&pid=264491
bat小白,请多指教!谢谢!

TOP

返回列表