如何解决批处理脚本中 "缺少操作数 "的问题?

问题描述 投票:0回答:2

我有一个批处理脚本,可以产生我想要的最终输出,但是在最终输出之前有两个 "缺少操作数 "的消息。 我在网上梳理了几十条线程,试图找出如何解决防止这些消息的方法,但我还没能找到解决方法......

这是我的脚本。

:Start
cls
@echo off

REM -------------------------------------------------------------------------
REM [ Remotely Verify Max RAM Capacity & Required Stick Sizes & Quantities) ]
REM -------------------------------------------------------------------------

Set /P "Computer=Enter the Computer Name: "

FOR /F "tokens=1,2 skip=1" %%G in ('wmic /node:"%Computer%" memphysical get MaxCapacity^, MemoryDevices') do (set /A "ramcapacity=%%G" & set /A "ramslots=%%H")
set /A "trueram=ramcapacity/1048576"
set /A "sticksizes=ramcapacity/1048576/ramslots"
echo Max RAM = %trueram%GB / %ramslots% sticks @ %sticksizes%GB

Goto End

:End

这是一个输出的例子 And here's an example of the output:

Missing operand.
Missing operand.
Max RAM = 64GB / 4 sticks @ 16GB

既然我能够得到我所期望的输出结果 缺少操作数的消息并不是什么大问题 但我还是想知道为什么会发生这种情况 以及如何防止它们发生(如果可能的话)。

windows for-loop batch-file variables cmd
2个回答
3
投票

那是因为 wcic 有那个丑陋的句子结尾的 CRCRLF 而不是仅仅 CRLF. 第一个 CR 成为变量的一部分 %%G%%H. 由于计算是正确的,你可以用以下方法抑制错误信息 2>nul. 要想真正解决这个问题,最安全和最通用的方法是用另一个 for 循环。

@echo off
setlocal
FOR /F "tokens=1,2 skip=1" %%G in ('wmic memphysical get MaxCapacity^, MemoryDevices') do (
  for /f %%a in ("%%G") do set "ramcapacity=%%a"
  for /f %%a in ("%%H") do set "ramslots=%%a"
)
set /A "trueram=ramcapacity/1048576"
set /A "sticksizes=ramcapacity/1048576/ramslots"
echo Max RAM = %trueram%GB / %ramslots% sticks @ %sticksizes%GB

注意: 你并不真的需要 set /a 之内 for 循环。简单地将一个数字分配给一个变量。set var=12345 即可。使用 set /a 只做运算。

另一种方法是避免在行末使用字符串。在下面的代码中,我添加了(但后来没有使用)第三个标记(Width - 最后一个 wmic memphysical作为 wmic 按字母顺序排列),因此,这两个 %%G%%H 不包括 CR. 我还用 ^|findstr /v "^$" 来跳过空行(这样会用空值覆盖我们的变量)。

@echo off
setlocal
FOR /F "skip=1 tokens=1,2" %%G in ('wmic memphysical get MaxCapacity^, MemoryDevices^,Width ^|findstr /v "^$"') do (
  set "ramcapacity=%%G"
  set "ramslots=%%H"
)
set /A "trueram=ramcapacity/1048576"
set /A "sticksizes=ramcapacity/1048576/ramslots"
echo Max RAM = %trueram%GB / %ramslots% sticks @ %sticksizes%GB 

2
投票

取而代之的是:

do (set /A "ramcapacity=%%G" & set /A "ramslots=%%H")

简单地写。

do (set /A "ramcapacity=%%G" & set /A "ramslots=%%H") 2> nul

The 2> nul 部分 只是抑制了错误信息。


错误信息的根本原因是由于 wmic 返回Unicode文本,其中 for /F 未能正确地将其转换为ASCIIANSI文本,因为它留下了无用的回车字符。所以,在你的情况下,在有内存信息的那行之后,在你的内存中加入 for /F 再迭代一次,使这样的字符在 %%G因此,试图通过 set /A "ramcapacity=%%G",最后返回错误信息。

为了避免这样的转换假象,可以将另一个 for /F 循环,像这样。

for /F "skip=1 delims=" %%I in ('
    wmic /NODE:"%Computer%" MemPhysical get MaxCapacity^,MemoryDevices
') do (
    for /F "tokens=1,2" %%G in ("%%I") do (
        set /A "ramcapacity=%%G" & set /A "ramslots=%%H"
    )
)

一般来说,我建议使用 /VALUE 的选择。wmic 命令,结果如下。

MaxCapacity=67108864
MemoryDevices=4

因为这样可以避免值串被右面的空格所填充 (尽管在你的情况下它们并不干扰,因为你使用的是 set /A):

set "ramcapacity=" & rem // (ensure this variable is initially undefined)
for /F "delims=" %%I in ('
    wmic /NODE:"%Computer%" MemPhysical get MaxCapacity^,MemoryDevices /VALUE
') do (
    for /F "tokens=2 delims==" %%J in ("%%I") do (
        rem // The condition ensures that the only first line is processed:
        if not defined ramcapacity set /A "ramcapacity=%%J"
        rem // Here is no condition, so the last (second) line is relevant:
        set /A "ramslots=%%J"
    )
)

我甚至会更进一步,避免明确定义变量,比如: ramcapacityramslots,因为返回的字符串 MaxCapacity=67108864MemoryDevices=4 看起来已经是完美的表情了 set 命令。

for /F "delims=" %%I in ('
    wmic /NODE:"%Computer%" MemPhysical get MaxCapacity^,MemoryDevices /VALUE
') do (
    for /F "delims=" %%J in ("%%I") do (
        rem // This implicitly defines variables `MaxCapacity` and `MemoryDevices`:
        set /A "%%J"
    )
)
set /A "TrueRAM=MaxCapacity/(1<<20), StickSizes=TrueRAM/MemoryDevices"
echo Max RAM = %TrueRAM% GiB / %MemoryDevices% sticks @ %StickSizes% GiB
© www.soinside.com 2019 - 2024. All rights reserved.