Командная строка Инструментарий управления 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 /?