Вопрос или проблема
Я пытаюсь перечислить различные записи в systemd-boot с помощью пакетного shell-скрипта, однако у меня возникают проблемы с разбором вывода команды и сохранением каждой записи в отдельную переменную.
Следующий фрагмент:
set NS="{4a67b082-0a4c-41cf-b6c7-440b29bb8c4f}"
set CMD="Get-UEFIVariable -Namespace \"%NS%\" -VariableName LoaderEntries"
powershell -ExecutionPolicy Bypass %CMD%
выводит
arch.confauto-windowsauto-reboot-to-firmware-setup
что соответствует моим ожиданиям, однако все записи, похоже, собраны в одну строку; согласно документации systemd-boot, (..) переменная EFI LoaderEntries может содержать серию идентификаторов загрузочных записей, один за другим, каждый завершается символом NUL (…).
Однако, при попытке перебора каждой записи с помощью:
for /f "tokens=1* delims=>NUL" %%F in ('powershell -ExecutionPolicy Bypass %CMD%') do set ENTRIES=%%F
echo %ENTRIES%
я получаю только одну строку с
a
Я не очень хорошо знаком с пакетными скриптами; как мне получить каждую загрузочную запись как отдельную переменную (чтобы, например, можно было искать конкретные записи)?
Ответ или решение
Парсинг последовательности строк с разделителем NUL в пакетном сценарии – это задача, которая требует нестандартного подхода из-за отсутствия нативной поддержки NUL-символа. Давайте подробно рассмотрим, как можно решить эту проблему в контексте вашего случая с systemd-boot.
Анализ проблемы
Вы пытаетесь обработать строку, содержащую несколько идентификаторов загрузчика, которые разделены символом NULL (NUL, \0). Этот символ специфичен и в пакетных скриптах интерпретируется как конец строки или его не учитывают вовсе, что затрудняет разбор строки на компоненты.
Возможные Решения
-
Использование PowerShell:
Поскольку символ NUL обычно интерпретируется как конец строки, работа с ним в пакетных скриптах Windows ограничена. PowerShell лучше справляется с обработкой подобных данных. Вы можете вывести данные в удобном для парсинга формате.
Пример решения с использованием PowerShell:
set NS="{4a67b082-0a4c-41cf-b6c7-440b29bb8c4f}" set CMD="Get-UEFIVariable -Namespace \"%NS%\" -VariableName LoaderEntries" for /f "delims=" %%i in ('powershell -ExecutionPolicy Bypass "%CMD% | ForEach-Object { $_ -join '' }" ') do ( set "entries=%%i" ) powershell -Command "[Text.Encoding]::UTF8.GetString(%entries%.TrimEnd([char]0)) -split [char]0" > entries.txt setlocal enabledelayedexpansion for /f "tokens=* delims=" %%j in (entries.txt) do ( set "entry=%%j" echo !entry! )
В этом коде мы используем PowerShell для преобразования байтов в строки без учета разделителей, а затем сплитуем строку по содержащимся нулям. Полученные данные сохраняем во временный файл, из которого пакетный скрипт считывает строки.
-
Дополнительные утилиты:
Если установлены сторонние инструменты, такие как
awk
илиsed
, их также можно задействовать для обработки данных.
Профессиональные Рекомендации
- Проверка зависимостей: Убедитесь, что ваша версия PowerShell поддерживает требуемые команды. У обновленных версий могут быть более мощные функциональные возможности для работы с бинарными данными.
- Удобочитаемость кода: Комментарии и структурирование кода облегчат сопровождение скрипта в будущем.
- Безопасность: Если скрипт используется в продуктивной среде, проверьте права доступа и корректность выполнения всех операций.
Заключение
Парсинг NUL-терминированных строк в пакетных скриптах может быть сложной задачей без использования дополнительных инструментов. PowerShell предоставляет отличные возможности для решения таких задач, что позволяет эффективно обрабатывать бинарные данные и разделять их на части.
Этот метод может быть адаптирован и для других задач, связанных с обработкой бинарных данных, что делает его универсальным инструментом в вашем арсенале.