为什么在处理 WMIC 输出和为变量赋值时输出错误消息 "Missing operand"?

Why is the error message "Missing operand" output on processing WMIC output and assigning a value to a variable?

我正在处理一个批处理文件,该文件应该显示当前估计的剩余电量。但是当我 运行 命令时,我得到了想要的结果加上错误消息 Missing operand. 输出。

我的代码:

FOR /F "delims= skip=1" %%i IN ('WMIC PATH Win32_Battery Get EstimatedChargeRemaining') DO (SET /a CHR=%%i)
ECHO "Battery Level: %CHR%"

我怎样才能摆脱不需要的输出Missing operand.

我已经尝试从最后一部分中删除 %,即 DO (SET /a CHR=i),但是当我这样做时,我最终得到 "Battery Level: 0",就好像它跳过了一些结果的数字。

这是因为 WMIC 输出中 100 之后的行。 WMIC 为我输出 4 行。它跳过第一行,然后继续其他行,只有其中一行有效。

@echo off
FOR /F "delims= skip=1" %%i IN ('WMIC PATH Win32_Battery Get EstimatedChargeRemaining') DO (
    SET /a CHR=%%i
    goto loopdone
)
:loopdone
ECHO "Battery Level: %CHR%"

Windows Management Instrumentation Command-line utility outputs text UTF-16 Little Endian encoded with byte order mark (BOM) 这意味着(几乎)每个字符总是有两个字节,而不显示 FF FE (BOM 作为十六进制字节)在输出文本的开头。

FOR 设计用于使用 ASCII/ANSI/OEM 编码解析文本,character encodings 每个字符仅使用一个字节。 运行ning 在命令提示符 window 中使用的代码页输出 window 命令 chcp 确定哪个字符由值在十进制范围 0 到 [=20 中的字节表示=] 或十六进制 00FF。默认情况下,Windows 命令行环境中使用的代码页取决于为使用的用户帐户设置的region/country/locale。

让我们看看发布的代码:

FOR /F "delims= skip=1" %%i IN ('WMIC PATH Win32_Battery Get EstimatedChargeRemaining') DO (SET /a CHR=%%i)
ECHO "Battery Level: %CHR%"

wmic 的输出例如 表示回车 return + 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字符表示

上面的代码导致在 FORcmd.exe /C 通过使用环境变量 cmd.exe /C 启动的单独命令进程中跳过 wmic 输出的第一行=27=] 在后台不显示 window 并被 FOR 捕获,仅包含值名称 EstimatedChargeRemaining.

包含一位、两位或三位感兴趣的值的第二行,根据值的位数,有 21 到 23 个空格首先分配给循环变量 i,然后分配给环境变量 CHR 使用算术表达式忽略尾随空格。

根据 Stephan on your previous question 的评论编写的代码在 Windows XP 上运行完美,但在 Windows 7 上会出现错误消息:

Missing operand.

在 Windows XP 上只有一个循环迭代,将带有 22 个尾随空格的值 93 和回车符 return 分配给环境变量 CHR,从而由于算术表达式,命令 SET 忽略空格和回车 return。

但是在 Windows 7 上,循环是第二次 运行,只有一个回车符 return 分配给循环变量 i。命令 SET 在计算算术表达式时忽略垂直空白字符 return,这导致在第二个循环迭代 set /a CHR= 上执行,因此确实存在语法正确的算术表达式缺少等号后的操作数。

关于解析 UTF-16 编码输出的 FOR 这个问题有多种可能的解决方案。

一个非常简单的方法是在将感兴趣的值分配给环境变量后退出 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%%%

因此 FOR 循环仅迭代一次并仅处理 wmic 输出的第二行,其中包含感兴趣的值和尾随空格。选项 delims= 定义一个空的分隔符列表是 not 用于获取在处理第二行时已被 FOR 删除的尾随空格从 wmic 的输出中捕获,因此循环变量 I 已经保存了感兴趣的值,没有尾随空格。这使得可以省略 SET 参数 /A 以在不使用算术表达式的情况下将值分配给环境变量。

解决 FOR 输出的 wmic 的 UTF-16 编码行结尾错误解析问题的另一个简单解决方案是使用如下代码:

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%%%

带有选项 /VALUEwmic 的输出例如 表示回车 return + 换行:

¶
¶
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             ; ............

所以开头有两个空行,即使是 UTF-16 编码,它们也总是被 FOR 忽略。然后是包含值名称和值之间有等号的行。最后还有两个空行。

两个 FOR 选项 tokens=2 delims== 导致在等号上拆分第三行,只分配等号后的第二个字符串作为循环的兴趣值变量 I,它被简单地分配到环境变量 CHR 旁边。命令 SET 仅执行一次,因为 wmic 输出结果末尾的空行解析错误导致只有一个子字符串只有回车符 return 被 FOR 所以它不能为循环变量 I 分配任何东西,因为没有第二个子字符串。因此 FOR 不会再次执行命令 SET

npocmaka as 通过使用第二个 FOR 循环来处理感兴趣值正确的行,发布了一个更简单的解决方案。

其他解决方案使用附加文件或附加命令将 UTF-16 编码文本输出为 ASCII 编码文本,FOR 可以毫无问题地捕获和处理这些文本。有关此类解决方案,请参阅 How to correct variable overwriting misbehavior when parsing output? 上的答案。

要了解使用的命令及其工作原理,请打开命令提示符 window,在其中执行以下命令,并仔细阅读为每个命令显示的所有帮助页面。

  • echo /?
  • for /?
  • goto /?
  • set /?
  • wmic /?
  • wmic PATH /?
  • wmic PATH Win32_Battery /?
  • wmic PATH Win32_Battery GET /?