#php #preg-match
#php #предварительное совпадение
Вопрос:
У меня есть несколько сотен строк, поступающих из файла субтитров VTT, пример из заголовка
00:01:03.500 --> 00:01:03.510 align:start position:0%
<c.colorCCCCCC>fourth guess it came from a broken</c><c.colorE5E5E5> home
</c>
00:01:03.510 --> 00:01:08.140 align:start position:0%
<c.colorCCCCCC>fourth guess it came from a broken</c><c.colorE5E5E5> home
a<00:01:04.580><c> father</c><00:01:05.580><c> not</c><00:01:05.820><c> being</c><00:01:05.880><c> there</c><00:01:06.890><c> my</c><00:01:07.890><c> mother</c></c>
00:01:08.140 --> 00:01:08.150 align:start position:0%
a<c.colorE5E5E5> father not being there my mother
</c>
00:01:08.150 --> 00:01:13.429 align:start position:0%
a<c.colorE5E5E5> father not being there my mother</c>
<c.colorE5E5E5>getting<00:01:09.150><c> married</c><00:01:09.630><c> and</c><00:01:11.360><c> the</c><00:01:12.360><c> abuse</c></c><c.colorCCCCCC><00:01:12.659><c> started</c><00:01:13.049><c> at</c></c>
00:01:13.429 --> 00:01:13.439 align:start position:0%
<c.colorE5E5E5>getting married and the abuse</c><c.colorCCCCCC> started at
</c>
Файлы субтитров VTT довольно запутанны, но цель состоит в том, чтобы захватить все слова в тегах временной метки и сами временные метки.
Я думал о предварительном совпадении, но не знаю, как этого добиться
$pattern = "<([^;]*)>";
preg_match_all($pattern, $lineContent, $allintag);
Это то, что я получил, но остановился на этом.
array(
00:01:03.510,
00:01:04.580,
00:01:05.58,
00:01:05.820,
00:01:05.880,
00:01:06.890,
00:01:07.890,
00:01:08.140,
00:01:09.150,
00:01:09.630,
00:01:11.360,
00:01:12.360,
00:01:12.659,
00:01:13.049
)
array(
'fourth guess it came from a broken home',
'father',
'not',
'being',
'there',
'my',
'mother',
'getting',
'married',
'and',
'the',
'abuse',
'started',
'at'
)
Комментарии:
1. Попробуйте
preg_match_all('~<(?<time>d{2}:d{2}:d{2}.d )>|<c>s*(?<text>.*?)</c>~', $lineContent, $allintag)
2. На полпути это возвращает массив только с временными кодами, а не со словами между одним тегом временного кода и следующим
3. Смотрите демонстрацию PHP и демонстрацию регулярных выражений .
4. Работает как шарм
5. Или, может быть 3v4l.org/00WmD лучше
Ответ №1:
Вы можете использовать
'~<(?<time>d{2}:d{2}:d{2}.d )><c>s*(?<text>.*?)</c>~'
Если временные и текстовые группы не являются последовательными, используйте
'~<(?<time>d{2}:d{2}:d{2}.d )>|<c>s*(?<text>.*?)</c>~'
Смотрите демонстрацию регулярных выражений.
Подробные сведения
<
—<
символ(?<time>d{2}:d{2}:d{2}.d )
— Группа «время»: 2 цифры,:
, 2 цифры,:
, 2 цифры,.
и затем 1 цифры>
—>
символ<c>
— буквенный<c>
текстs*
— 0 пробелов(?<text>.*?)
— Группа «текст»: любые символы 0 , отличные от символов разрыва строки, как можно меньше</c>
— буквенный</c>
текст.
Смотрите демонстрацию PHP:
$lineContent = "<00:01:13.650><c> time</c><00:01:13.920><c> and</c>
<00:01:14.780><c> that's</c><00:01:15.780><c> what</c>";
if (preg_match_all('~<(?<time>d{2}:d{2}:d{2}.d )><c>s*(?<text>.*?)</c>~', $lineContent, $allintag)) {
print_r($allintag["time"]);
print_r($allintag["text"]);
}
Вывод:
Array ( [0] => 00:01:13.650 [1] => 00:01:13.920 [2] => 00:01:14.780 [3] => 00:01:15.780 )
Array ( [0] => time [1] => and [2] => that's [3] => what )
Комментарии:
1. Хорошо, он все еще пропускает несколько слов. Смотрите отредактированный код
2. @PeterFriedlander Попробуйте
'~<(?<time>d{2}:d{2}:d{2}.d )>|<c(?:.color(?:[a-fA-F0-9]{2}){3})?>s*(?<text>.*?)</c>~s'
, посмотрите эту демонстрацию3. Спасибо! Но я вставил формулу в код регулярного выражения и даже в демонстрационную ссылку, но она неправильно форматируется.
4. @PeterFriedlander У вас рекурсивная структура в ваших данных. Следовательно, неясно, что вам нужно получить. Пожалуйста, объясните, какой результат вы хотите получить.