Я ищу, чтобы просмотреть существующие файлы .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?
Спасибо заранее за любые предложения.
РЕДАКТИРОВАТЬ—
Ниже дамп $ 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) {}
}
Проблема с вашим регулярным выражением — плохая обработка конца строки.
У вас есть это в конце: \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
Это выглядит ужасно, но это работает.
Примечание: я обмениваюсь между \R
а также \r\n
так как \R
соответствует буквальному R
внутри []
,
Данные записываются так:
Вы можете примерить это на 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
Других решений пока нет …