Batch file 为什么在处理WMIC输出并为变量赋值时会输出错误消息“缺少操作数”?

Batch file 为什么在处理WMIC输出并为变量赋值时会输出错误消息“缺少操作数”?,batch-file,cmd,wmic,Batch File,Cmd,Wmic,我正在处理一个批处理文件,该文件应该显示当前估计的剩余费用。但当我运行该命令时,我得到了期望的结果加上错误消息“缺少操作数”。输出 我的代码: FOR /F "delims= skip=1" %%i IN ('WMIC PATH Win32_Battery Get EstimatedChargeRemaining') DO (SET /a CHR=%%i) ECHO "Battery Level: %CHR%" 我怎样才能摆脱那个不需要的输出缺少操作数 我已经尝试从最后一部分中删除%,即DO

我正在处理一个批处理文件,该文件应该显示当前估计的剩余费用。但当我运行该命令时,我得到了期望的结果加上错误消息“缺少操作数”。输出

我的代码:

FOR /F "delims= skip=1" %%i IN ('WMIC PATH Win32_Battery Get EstimatedChargeRemaining') DO (SET /a CHR=%%i)
ECHO "Battery Level: %CHR%"
我怎样才能摆脱那个不需要的输出缺少操作数


我已经尝试从最后一部分中删除%,即DO SET/a CHR=I,但当我这样做时,我得到的电池电量为: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%"

这是因为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%"
该实用程序输出用BOM编码的文本Little Endian,这意味着几乎总是每个字符有两个字节,输出文本的开头不显示为十六进制字节的FF FE BOM

FOR设计用于使用ASCII/ANSI/OEM编码解析文本,每个字符仅使用一个字节。通过在命令提示符窗口中运行命令chcp确定哪个字符由值在十进制范围0到255或十六进制00到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                                           ; ..
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             ; ............
格式为:十六进制偏移量:十六进制字节;Windows-1252字符表示法

上述代码导致在单独的命令过程中跳过wmic的第一行输出,该命令过程由cmd.exe/C在后台使用环境变量ComSpec启动,不显示窗口,并由FOR捕获,仅包含值名称EstimatedChargerMaining

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

这段代码是根据您对上一个问题的评论编写的,在Windows XP上运行得非常好,但在Windows 7上会出现错误消息:

缺少操作数

在Windows XP上,只有一次循环迭代,将值93与22个尾随空格和回车符赋给环境变量CHR,由于算术表达式的原因,命令集将忽略空格和回车符

但在Windows7上,循环会再次运行,并且只为循环变量i分配了一个回车符。算术表达式求值时的命令集忽略垂直空格字符回车,这将导致在第二个循环迭代集/a CHR=上执行,因此语法正确的算术表达式确实缺少等号后有一个操作数

对于解析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%%%
因此FOR循环只迭代一次,只处理wmic输出的第二行,其中包含感兴趣的值和尾随空格。Option delims=用于定义空分隔符列表的选项不用于获取在处理从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%%%
带有选项/值的wmic的输出例如带有¨表示回车+换行:

¶
¶
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                                           ; ..
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的感兴趣值,循环变量I仅分配在环境变量CHR的旁边。c ommand SET只执行一次,因为wmic输出末尾的错误解析空行只会导致FOR找到一个子字符串,且仅包含回车符,因此它无法将任何内容分配给循环变量I,因为没有第二个子字符串。因此,不会再次执行命令集

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

其他解决方案使用附加文件或附加命令将UTF-16编码文本输出为ASCII编码文本,以便捕获和处理而不会出现任何问题。有关此类解决方案,请参见上的答案

要了解所使用的命令及其工作方式,请打开命令提示符窗口,在其中执行以下命令,并非常仔细地阅读为每个命令显示的所有帮助页面

回声/? 对于/? 转到/? 集/? wmic/? wmic路径/? wmic路径Win32_电池/? wmic路径Win32_电池获取/? 该实用程序输出用BOM编码的文本Little Endian,这意味着几乎总是每个字符有两个字节,输出文本的开头不显示为十六进制字节的FF FE BOM

FOR设计用于使用ASCII/ANSI/OEM编码解析文本,每个字符仅使用一个字节。通过在命令提示符窗口中运行命令chcp确定哪个字符由值在十进制范围0到255或十六进制00到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                                           ; ..
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             ; ............
格式为:十六进制偏移量:十六进制字节;Windows-1252字符表示法

上述代码导致在单独的命令过程中跳过wmic的第一行输出,该命令过程由cmd.exe/C在后台使用环境变量ComSpec启动,不显示窗口,并由FOR捕获,仅包含值名称EstimatedChargerMaining

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

这段代码是根据您对上一个问题的评论编写的,在Windows XP上运行得非常好,但在Windows 7上会出现错误消息:

缺少操作数

在Windows XP上,只有一次循环迭代,将值93与22个尾随空格和回车符赋给环境变量CHR,由于算术表达式的原因,命令集将忽略空格和回车符

但在Windows7上,循环会再次运行,并且只为循环变量i分配了一个回车符。算术表达式求值时的命令集忽略垂直空格字符回车,这将导致在第二个循环迭代集/a CHR=上执行,因此语法正确的算术表达式确实缺少等号后有一个操作数

对于解析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%%%
因此FOR循环只迭代一次,只处理wmic输出的第二行,其中包含感兴趣的值和尾随空格。Option delims=用于定义空分隔符列表的选项不用于获取在处理从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%%%
带有选项/值的wmic的输出例如带有¨表示回车+换行:

¶
¶
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                                           ; ..
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的感兴趣值,循环变量I仅分配在环境变量CHR的旁边。 命令集只执行一次,因为wmic输出末尾错误的解析空行只会导致FOR找到一个子字符串,且仅返回回车符,因此它无法为循环变量I赋值,因为没有第二个子字符串。因此,不会再次执行命令集

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

其他解决方案使用附加文件或附加命令将UTF-16编码文本输出为ASCII编码文本,以便捕获和处理而不会出现任何问题。有关此类解决方案,请参见上的答案

要了解所使用的命令及其工作方式,请打开命令提示符窗口,在其中执行以下命令,并非常仔细地阅读为每个命令显示的所有帮助页面

回声/? 对于/? 转到/? 集/? wmic/? wmic路径/? wmic路径Win32_电池/? wmic路径Win32_电池获取/?
你的or出了什么问题?根据你的建议,我最终使用了aschipfl的建议,我之前忽略了这一建议,原因有二:,一个是我和前一个用户有一个正在工作的awnser,两个是我无法理解的。在你的you goto结果中,避免了你描述的错误…你的or有什么问题?根据你的建议,我最终使用了aschipfl的建议,我之前忽略了这一建议,原因有两个,一个是我和前一个用户有一个正在工作的awnser,另两个是我无法理解它。在你的示例中,你得到的结果避免了你描述的错误。。。