The Windows 管理规范命令行实用程序输出文本UTF-16Little Endian 编码为字节顺序标记(BOM) 这意味着(几乎)每个字符总是有两个字节且不显示FF FE
(BOM 作为十六进制字节)位于输出文本的开头。
FOR设计用于使用 ASCII/ANSI/OEM 编码解析文本,这些编码是字符编码每个字符仅使用一个字节。通过在命令提示符窗口中运行命令来输出所使用的代码页chcp
确定哪个字符由十进制范围内的字节表示0
to 255
或十六进制00
to FF
。默认情况下,Windows 命令行环境中使用的代码页取决于为所使用的用户帐户设置的区域/国家/地区。
让我们看一下发布的代码:
FOR /F "delims= skip=1" %%i IN ('WMIC PATH Win32_Battery Get EstimatedChargeRemaining') DO (SET /a CHR=%%i)
ECHO "Battery Level: %CHR%"
的输出wmic
例如是¶
代表 Windows 7 和 Windows XP 上的回车+换行:
EstimatedChargeRemaining ¶
93 ¶
此输出重定向到文件并查看十六进制,如下所示:
0000h: FF FE 45 00 73 00 74 00 69 00 6D 00 61 00 74 00 ; ÿþE.s.t.i.m.a.t.
0010h: 65 00 64 00 43 00 68 00 61 00 72 00 67 00 65 00 ; e.d.C.h.a.r.g.e.
0020h: 52 00 65 00 6D 00 61 00 69 00 6E 00 69 00 6E 00 ; R.e.m.a.i.n.i.n.
0030h: 67 00 20 00 20 00 0D 00 0A 00 39 00 33 00 20 00 ; g. . .....9.3. .
0040h: 20 00 20 00 20 00 20 00 20 00 20 00 20 00 20 00 ; . . . . . . . .
0050h: 20 00 20 00 20 00 20 00 20 00 20 00 20 00 20 00 ; . . . . . . . .
0060h: 20 00 20 00 20 00 20 00 20 00 20 00 20 00 0D 00 ; . . . . . . ...
0070h: 0A 00 ; ..
格式为:十六进制偏移量:十六进制字节;Windows-1252 字符表示
上面的代码导致跳过第一行输出wmic
在由以下命令启动的单独命令进程中FOR with cmd.exe /C
通过使用环境变量ComSpec
在后台不显示窗口并捕获FOR仅包含值名称EstimatedChargeRemaining
.
第二行包含感兴趣的值,具有一位、两位或三位数字,根据值的位数有 21 到 23 个空格,首先将其分配给循环变量i
和环境变量旁边CHR
使用算术表达式忽略尾随空格。
这段代码是根据评论编写的Stephan关于你之前的问题如何在 WMIC 结果中获得没有不需要空格的值?在 Windows XP 上运行完美,但在 Windows 7 上会出现错误消息:
缺少操作数。
在 Windows XP 上,只有一次循环迭代来分配值93
带有 22 个尾随空格和回车符到环境变量CHR
其中空格和回车符被命令忽略SET因为算术表达式。
但在 Windows 7 上,循环第二次运行,仅将回车符分配给循环变量i
。命令忽略垂直空白字符回车符SET对算术表达式求值,导致在第二次循环迭代中执行set /a CHR=
因此,对于语法正确的算术表达式来说,等号后面确实缺少一个操作数。
对于这个问题有多种解决方案FOR解析 UTF-16 编码输出。
一个非常简单的退出FOR将感兴趣的值分配给环境变量后循环。
for /F "skip=1" %%I in ('%SystemRoot%\System32\wbem\wmic.exe PATH Win32_Battery GET EstimatedChargeRemaining') do set "CHR=%%I" & goto HaveValue
:HaveValue
echo Battery level: %CHR%%%
So the FOR循环仅迭代一次并仅处理第二行wmic
输出带有感兴趣的值和尾随空格。选项delims=
定义一个空的分隔符列表是not用于获取已删除的尾随空格FOR处理从输出捕获的第二行wmic
所以循环变量I
已经保存了兴趣值,没有尾随空格。这使得可以省略SET范围/A
仅将值分配给环境变量而不使用算术表达式。
解决 UTF-16 编码行结尾错误解析问题的另一个简单解决方案wmic
输出由FOR使用这样的代码:
for /F "tokens=2 delims==" %%I in ('%SystemRoot%\System32\wbem\wmic.exe PATH Win32_Battery GET EstimatedChargeRemaining /VALUE') do set "CHR=%%I"
echo Battery level: %CHR%%%
的输出wmic
有选项/VALUE
例如是¶
代表回车+换行:
¶
¶
EstimatedChargeRemaining=93¶
¶
¶
此输出重定向到文件并查看十六进制,如下所示:
0000h: FF FE 0D 00 0A 00 0D 00 0A 00 45 00 73 00 74 00 ; ÿþ........E.s.t.
0010h: 69 00 6D 00 61 00 74 00 65 00 64 00 43 00 68 00 ; i.m.a.t.e.d.C.h.
0020h: 61 00 72 00 67 00 65 00 52 00 65 00 6D 00 61 00 ; a.r.g.e.R.e.m.a.
0030h: 69 00 6E 00 69 00 6E 00 67 00 3D 00 39 00 33 00 ; i.n.i.n.g.=.9.3.
0040h: 0D 00 0A 00 0D 00 0A 00 0D 00 0A 00 ; ............
所以开头有两个空行,总是被忽略FOR即使是 UTF-16 编码。然后是包含值名称和其间带有等号的值的行。最后还有两行空行。
The two FOR选项tokens=2 delims==
导致在等号上分割第三行,并在等号之后仅分配第二个字符串作为循环变量感兴趣的值I
它只是分配在环境变量旁边CHR
。命令SET由于末尾的空行解析错误,仅执行一次wmic
输出结果仅在一个子字符串中,仅找到回车符FOR所以它不能给循环变量分配任何东西I
因为没有第二个子字符串。是因为FOR不执行命令SET第二次。
发布了一个更简单的解决方案npocmaka as 回答你之前的问题通过使用第二个FOR循环处理感兴趣值正确的行。
其他解决方案使用附加文件或附加命令将 UTF-16 编码文本输出为 ASCII 编码文本,其中FOR可以毫无问题地捕获和处理。查看答案解析输出时如何纠正变量覆盖错误行为?对于这样的解决方案。
为了了解所使用的命令及其工作原理,请打开命令提示符窗口,执行以下命令,并仔细阅读为每个命令显示的所有帮助页面。
echo /?
for /?
goto /?
set /?
wmic /?
wmic PATH /?
wmic PATH Win32_Battery /?
wmic PATH Win32_Battery GET /?