Почему выводится сообщение об ошибке «Отсутствует операнд» при обработке вывода WMIC и присвоении значения переменной? - PullRequest
0 голосов
/ 29 ноября 2018

Я работаю над пакетным файлом, который должен показывать оставшийся на данный момент расчетный заряд.Но когда я запускаю команду, я получаю желаемый результат плюс сообщение об ошибке Missing operand. output.

Мой код:

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", как если бы он пропускал некоторые числа из результата.

Ответы [ 2 ]

0 голосов
/ 30 ноября 2018

Командная строка Инструментарий управления Windows выводит текст UTF-16 Little Endian, закодированный с меткой порядка байтов (BOM), что означает (почти) всегдас двумя байтами на символ, при этом не отображается FF FE (спецификация в шестнадцатеричных байтах) в начале выходного текста.

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

Формат: шестнадцатеричное смещение: шестнадцатеричные байты; Представление символов Windows-1252

Приведенный выше код приводит к пропуску вывода первой строки на wmic в отдельном командном процессе, запущенном FOR с cmd.exe /C с помощьюиспользование переменной окружения ComSpec в фоновом режиме без отображения окна и захватывается FOR , содержащим только имя значения EstimatedChargeRemaining.

Вторая строка, содержащая интересующее значение с одним, двумя илитри цифры с 21 до 23 пробелами в зависимости от цифр значения назначаются сначала переменной цикла i, а затем - переменной окружения CHR с использованием арифметического выражения для игнорирования конечных пробелов.

Этот код написан в соответствии сна комментарий Stephan к вашему предыдущему вопросу Как получить значение без лишних пробелов в результатах WMIC? отлично работает в Windows XP, но приводит к Windows 7 в сообщении об ошибке:

Отсутствует операнд.

В Windows XP есть только одна итерация цикла с назначениемng значение 93 с 22 конечными пробелами и возврат каретки к переменной окружения CHR, в результате чего пробелы и возврат каретки игнорируются командой SET из-за арифметического выражения.

Но в Windows 7 цикл запускается второй раз, и для переменной цикла i назначается только возврат каретки.Возврат вертикального переноса пробельного символа игнорируется командой SET при вычислении арифметического выражения, которое приводит к выполнению на итерации второго цикла set /a CHR=, и поэтому действительно существует операнд после знака равенства, пропущенный для синтаксически правильной арифметикиexpression.

Существует несколько возможных решений этой проблемы 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%%%

Таким образом, цикл FOR повторяется только один раз и обрабатывает только вторую строку вывода wmic со значениеминтерес и замыкающие пробелы.Опция delims= для определения пустого списка разделителей не используется для получения конечных пробелов, уже удаленных 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.Затем идет строка, содержащая имя значения и значение со знаком равенства между ними.Наконец, есть еще две пустые строки.

Две FOR опции tokens=2 delims== приводят к разбиению третьей строки на знак равенства с назначением только второй строки после знака равенства, являющегося значениеминтерес к переменной цикла I, которая просто присваивается рядом с переменной окружения CHR.Команда SET выполняется только один раз из-за неправильного разбора пустых строк в конце wmic результата результата только в одной подстроке с найденным FOR только возвратом каретки, и поэтому она не можетприсвойте что-нибудь переменной цикла I, поскольку второй подстроки нет.По этой причине FOR не выполняет команду SET во второй раз.

Еще одно простое решение было опубликовано npocmaka как ответьте на предыдущий вопрос , используя второй цикл FOR для обработки строки с правильным значением интереса.

Другие решения используют дополнительный файл или дополнительную команду для вывода UTF.Кодированный -16 текст как текст в кодировке ASCII, который FOR может захватывать и обрабатывать без проблем.См. Ответы по Как исправить неправильное поведение при перезаписи переменных при синтаксическом анализе выходных данных? для таких решений.

Для понимания используемых команд и их работы откройте окно командной строки и выполните следующие командыи внимательно прочитайте все справочные страницы, отображаемые для каждой команды.

  • echo /?
  • for /?
  • goto /?
  • set /?
  • wmic /?
  • wmic PATH /?
  • wmic PATH Win32_Battery /?
  • wmic PATH Win32_Battery GET /?
0 голосов
/ 29 ноября 2018

Это происходит из-за строк, которые идут после 100 в выводе WMIC.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%"
...