PHP Regex для файлов .vtt - PullRequest
       9

PHP Regex для файлов .vtt

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

Я пытаюсь перебрать существующие файлы .vtt и прочитать данные меток в базу данных.

Формат файлов .vtt:

WEBVTT FILE

line1
00:00:00.000 --> 00:00:10.000
‘Stuff’

line2
00:00:10.000 --> 00:00:20.000
Other stuff
Example with 2 lines

line3
00:00:20.00 --> 00:00:30.000
Example with only 2 digits in milliseconds

line4
00:00:30.000 --> 00:00:40.000
Different stuff

00:00:40.000 --> 00:00:50.000
Example without a head line

Первоначально я пыталсяиспользовать ^ и $, чтобы быть достаточно регламентированным со строками вдоль линий: /^(\w*)$^(\d{2}):(\d{2}):(\d{2})\.(\d{2,3}) --> (\d{2}):(\d{2}):(\d{2})\.(\d{2,3})$^(.+)$/ims, но я изо всех сил пытался заставить это работать в контролере регулярных выражений и прибегнул к использованию \s для обработки начала / конца строки.

В настоящее время я использую следующее регулярное выражение: /(.*)\s(\d{2}):(\d{2}):(\d{2})\.(\d{2,3}) --> (\d{2}):(\d{2}):(\d{2})\.(\d{2,3})\s(.+)/im

Это частично работает с использованием онлайн-проверок регулярных выражений, таких как: https://regex101.com/r/mmpObk/3 (этот пример не принимает многострочные субтитры,но получает первую строку, которая на данный момент достаточно хороша для моей цели, так как все субтитры в настоящее время 1 строки).Однако, если я помещу это в php (preg_match_all("/(.*)\s(\d{2}):(\d{2}):(\d{2})\.(\d{2,3}) --> (\d{2}):(\d{2}):(\d{2})\.(\d{2,3})\s(.+)/mi", $fileData, $matches)) и выведу результаты, я получу массив пустых массивов.

Что может быть разным между онлайн-регулярным выражением и php?

Заранее спасибодля любых предложений.

EDIT --- Ниже дамп $ fileData и дамп $ match:

string(341) "WEBVTT FILE

line1
00:00:00.000 --> 00:00:10.000
‘Stuff’

line2
00:00:10.000 --> 00:00:20.000
Other stuff
Example with 2 lines

line3
00:00:20.00 --> 00:00:30.000
Example with only 2 digits in milliseconds

line4
00:00:30.000 --> 00:00:40.000
Different stuff

00:00:40.000 --> 00:00:50.000
Example without a head line"

array(11) {
    [0]=>
        array(0) {}
    [1]=>
        array(0) {}
    [2]=>
        array(0) {}
    [3]=>
        array(0) {}
    [4]=>
        array(0) {}
    [5]=>
        array(0) {}
    [6]=>
        array(0) {}
    [7]=>
        array(0) {}
    [8]=>
        array(0) {}
    [9]=>
        array(0) {}
    [10]=>
        array(0) {}
}

1 Ответ

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

Проблема с вашим регулярным выражением - плохая обработка конца строки.

В конце у вас есть это: \s(.+)/mi.
Это соответствует только 1 пробелу, но новые строки могут быть 1 или 2 пробелами.

Чтобы исправить это, вы можете использовать \R(.+)/mi.

. Он работает на веб-сайте, потому что он нормализует ваши новые строки в новые строки в стиле Linux.
То есть в стиле Windowsсимволы новой строки \r\n (2 символа) и стиль Linux * \n (1 символ).


В качестве альтернативы, вы можете попробовать это регулярное выражение:

/(?:line(\d+)\R)?(\d{2}(?::\d{2}){2}\.\d{2,3})\s*-->\s*(\d{2}(?::\d{2}){2}\.\d{2,3})\R((?:[^\r\n]|\r?\n[^\r\n])*)(?:\r?\n\r?\n|$)/i

Itвыглядит ужасно, но работает.
Примечание: я переключаюсь между \R и \r\n, потому что \R соответствует буквальному R внутри [].

Данные записываются какэто:

  1. Номер строки (если имеется)
  2. Начальная временная метка
  3. Конечная временная метка
  4. Многострочный текст

Вы можете попробовать это на https://regex101.com/r/Yk8iD1/1

. Вы можете использовать удобный генератор кода для генерации следующего PHP:

$re = '/(?:line(\d+)\R)?(\d{2}(?::\d{2}){2}\.\d{2,3})\s*-->\s*(\d{2}(?::\d{2}){2}\.\d{2,3})\R((?:[^\r\n]|\r?\n[^\r\n])*)(?:\r?\n\r?\n|$)/i';
$str = 'WEBVTT FILE

line1
00:00:00.000 --> 00:00:10.000
‘Stuff’

line2
00:00:10.000 --> 00:00:20.000
Other stuff
Example with 2 lines

line3
00:00:20.00 --> 00:00:30.000
Example with only 2 digits in milliseconds

line4
00:00:30.000 --> 00:00:40.000
Different stuff

00:00:40.000 --> 00:00:50.000
Example without a head line';

preg_match_all($re, $str, $matches, PREG_SET_ORDER, 0);

// Print the entire match result
var_dump($matches);

Вы можете проверить это на http://sandbox.onlinephpfunctions.com/code/7f5362f56e912f3504ed075e7013071059cdee7b

...