Board logo

标题: [其他] [分享]批处理用for /f从wmic的结果中正确取值 [打印本页]

作者: buyiyang    时间: 2023-4-7 15:38     标题: [分享]批处理用for /f从wmic的结果中正确取值

据我观察,如何用for /f从wmic的结果中正确取值的问题还是困扰了许多人,一开始我也被困扰过,比如执行以下命令来获取ExecutablePath:
  1. for /f "delims=" %%i in ('wmic process where "Name='WMIC.exe'" get ExecutablePath') do echo %%i
复制代码
cmd窗口回显是这样的(加了个注意方便观察):
  1. >for /F "delims=" %i in ('wmic process where "Name='WMIC.exe'" get ExecutablePath') do echo %i注意
  2. 注意 >echo ExecutablePath
  3. 注意utablePath
  4. 注意 >echo C:\windows\System32\Wbem\WMIC.exe
  5. 注意indows\System32\Wbem\WMIC.exe
  6. 注意 >echo
  7. 注意
复制代码
你会发现“注意”这两个字跑到前面去了,这是为什么呢?把wmic process where "Name='WMIC.exe'" get ExecutablePath的结果重定向到文件里,然后用编辑器打开:
  1. ExecutablePath                     
  2. C:\windows\System32\Wbem\WMIC.exe  
复制代码
你会发现有结果有三行,第一行和第二行行尾有若干个空格,还有一个回车符\r,第三行仅有一个回车符。
如果你把wmic process where "Name='WMIC.exe'" get ExecutablePath /value的结果重定向到文件:
  1. ExecutablePath=C:\windows\System32\Wbem\WMIC.exe
复制代码
结果有五行,首尾几个空行仅有一个回车符,第三行行尾多一个回车符,即以\r\r\n结尾。
问题就出在多余的\r上,回车符即回到行首,明白了问题所在,出现以下情况也就不足为奇了:
  1. >for /F "delims=" %i in ('wmic process where "Name='WMIC.exe'" get ExecutablePath') do set "p=%i"
  2. " >set "p=ExecutablePath
  3. " >set "p=C:\windows\System32\Wbem\WMIC.exe
  4. " >set "p=
  5. >echo
  6. ECHO 处于打开状态。
复制代码
那么如何解决这个问题从而正确取值呢?分常用的两种情况,有无/value开关:
一、无/value开关
1、在这种情况下,前面说了,有效行行尾有若干个空格和一个回车符\r,末行有一个回车符。可以用空格分割并舍弃行尾回车符(for /f的默认分隔符就是空格和跳格),用"findstr ."过滤末行回车符(findstr通配符.不匹配\r或\n)
  1. for /f  %%i in ('wmic process where "Name='WMIC.exe'" get ExecutablePath ^| findstr .') do set "p=%%i"
  2. echo %p%
复制代码
2、除了findstr外还有一种方法可以过滤末行回车符
  1. for /f "tokens=2" %%i in ('wmic process where "Name='WMIC.exe'" get Caption^,ExecutablePath') do set "p=%%i"
  2. echo %p%
复制代码
因为末行只有\r一个字段,没有第二个字段,所以不会取到末行。但还有一种情况(注意tokens):
  1. >for /F "tokens=1-2" %i in ('wmic process where "Name='WMIC.exe'" get Caption,ExecutablePath') do set "p=%%j"
  2. >set "p=ExecutablePath"
  3. >set "p=C:\windows\System32\Wbem\WMIC.exe"
  4. >set "p="
  5. >echo
  6. ECHO 处于打开状态。
复制代码
它仍然读取了末行,并将末行不存在的第二个字段空值赋给了%%j,与之前不同的是它判断末行第一个字段存在并将\r赋给了%%i。
二、有/value开关
前面说了,在这种情况下,首尾几个空行有一个回车符,有效行行尾多一个回车符,大家一般是这么用的:
  1. for /f "tokens=2 delims==" %%i in ('wmic process where "Name='WMIC.exe'" get ExecutablePath /value') do set "p=%%i"
复制代码
这自然地运用了前面第二种方法排除仅有回车符的空行,然后问题就是去除有效行行尾的回车符,这里介绍几种方法:
1、set不加引号
  1. for /f "tokens=2 delims==" %%i in ('wmic process where "Name='WMIC.exe'" get ExecutablePath /value') do set p=%%i
复制代码
2、使用call
http://www.bathome.net/redirect.php?goto=findpost&pid=265622&ptid=65408
3、for /f处理字符串
http://www.bathome.net/redirect.php?goto=findpost&pid=267090&ptid=65704

如有错漏,还望指教。
作者: lancer    时间: 2023-4-7 16:54

写的很好,仔细拜读了一下,能明白一些了。。。主要是我比较菜,没怎么用过wmic,还是要深入学习一下wmic才行。。。
作者: Five66    时间: 2023-4-7 20:22

貌似新版的ps都不支持传统的wmic了,只有封装wmic的cmdlet....
作者: newswan    时间: 2023-4-8 10:34

回复 3# Five66


嗯, wmic 的输出是有点讨厌
微软的垃圾堆
作者: jorlaying    时间: 2023-4-16 11:16

本帖最后由 jorlaying 于 2023-4-16 11:54 编辑

楼主 按照你的方法遇到一个问题,请看代码,如何解决?
  1. @echo off & setlocal enabledelayedexpansion  
  2. for /f %%i in ('wmic logicaldisk get Description^| findstr .') do set "Description=%%i"
  3. echo,%Description%
  4. pause
复制代码
Local Fixed Disk只能读取到Local  空格后面的部分没有了。不能完整显示,set已加引号
还有就是用这个方法,输出的后面都会带一个空格符
作者: buyiyang    时间: 2023-4-16 15:46

回复 5# jorlaying


    第一个这个是空白分割符引起的,属性的值是空格分割的,如果值本身有空格就会取错,试试“二、有/value开关”的方法。第二个应该不会有空格吧,因为空格已经作为分割符了。
作者: Batcher    时间: 2023-4-16 17:31

回复 5# jorlaying
  1. @echo off
  2. for /f "delims=" %%i in ('wmic logicaldisk get Description ^| findstr .') do (
  3.     for %%j in ("%%i") do (
  4.         set "Description=%%~j"
  5.     )
  6. )
  7. echo,%Description%
  8. pause
复制代码

作者: buyiyang    时间: 2023-4-16 23:45

回复 7# Batcher


    不过这样%Description%会带有空格。
作者: Batcher    时间: 2023-4-17 10:04

回复 8# buyiyang


    是的,这是wmic命令结果里面自己带的空格。




欢迎光临 批处理之家 (http://bbs.bathome.net/) Powered by Discuz! 7.2