Проблема с анализом большого файла M3U - PullRequest
1 голос
/ 15 июня 2019

Файл M3U представляет собой файл списка воспроизведения, он содержит список записей, описывающих медиа-файлы, их имена, идентификаторы, категории и т. Д. В первой строке находятся метаданные, а во второй строке - файл или потоковый URL.

Пример:

#EXTINF:-1 tvg-id="ChannelName" tvg-name="|FR| Channel" tvg-logo="http://logo" timeshift="1" group-title="|FR| FrenchChannel",|FR| Channel Fullname
URL

Мой файл содержит около 90 000 записей и 160 000 строк.Весит около 20Мб.

Я хочу разобрать этот файл и получить каждую запись.Я попытался использовать это регулярное выражение:

'(.+?),(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)(.+)\s*(.+)\s*'

Он возвращает мне метаданные, полное имя и URL в разных соответствующих группах.Он отлично работает на разных подмножествах, 30000 и 50000 строк.Однако при работе над полным набором сопоставление занимает слишком много времени.В тот момент, когда я не мог позволить этому завершиться и должен был прекратить его.

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

1 Ответ

2 голосов
/ 15 июня 2019

Один из вариантов может заключаться в том, чтобы повторять пары ключ-значение вместо использования не жадного .+?, чтобы предотвратить ненужное возвращение в исходное состояние и пропустить положительный взгляд (?=:

^(#\S+(?:\s+[^\s="]+="[^"]+")+),(.*)\s*(.*)

Объяснение

  • ^ Начало строки
  • ( Первая группа захвата
    • #\S+ Match # с последующим 0+ раз непробельным символом
    • (?: [^\s="]+="[^"]+")+ Повторите 1+ раз пару значений ключа, перед которыми 1+ умножается на символ пробела
  • ) Закрыть группу 1
  • ,(.*) Подберите запятую и захватите 0+ раз любого персонажа в группе 2
  • \s* Соответствует 0+ раз символу пробела
  • (.*) Захват в группе 3, соответствующий любому символу 0+ раз

Regex demo

...