Как разобрать последовательность строк, заканчивающихся NUL, в пакетном скрипте?

Вопрос или проблема

Я пытаюсь перечислить различные записи в 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). Этот символ специфичен и в пакетных скриптах интерпретируется как конец строки или его не учитывают вовсе, что затрудняет разбор строки на компоненты.

Возможные Решения

  1. Использование 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 для преобразования байтов в строки без учета разделителей, а затем сплитуем строку по содержащимся нулям. Полученные данные сохраняем во временный файл, из которого пакетный скрипт считывает строки.

  2. Дополнительные утилиты:

    Если установлены сторонние инструменты, такие как awk или sed, их также можно задействовать для обработки данных.

Профессиональные Рекомендации

  • Проверка зависимостей: Убедитесь, что ваша версия PowerShell поддерживает требуемые команды. У обновленных версий могут быть более мощные функциональные возможности для работы с бинарными данными.
  • Удобочитаемость кода: Комментарии и структурирование кода облегчат сопровождение скрипта в будущем.
  • Безопасность: Если скрипт используется в продуктивной среде, проверьте права доступа и корректность выполнения всех операций.

Заключение

Парсинг NUL-терминированных строк в пакетных скриптах может быть сложной задачей без использования дополнительных инструментов. PowerShell предоставляет отличные возможности для решения таких задач, что позволяет эффективно обрабатывать бинарные данные и разделять их на части.

Этот метод может быть адаптирован и для других задач, связанных с обработкой бинарных данных, что делает его универсальным инструментом в вашем арсенале.

Оцените материал
Добавить комментарий

Капча загружается...