Разобрать файл субтитров с использованием регулярного выражения C#

StackOverflow https://stackoverflow.com/questions/1765026

  •  21-09-2019
  •  | 
  •  

Вопрос

Мне нужно найти номер, точки входа и выхода тайм-кода и все строки текста.

9
00:09:48,347 --> 00:09:52,818
- Let's see... what else she's got?
- Yea... ha, ha.

10
00:09:56,108 --> 00:09:58,788
What you got down there, missy?

11
00:09:58,830 --> 00:10:00,811
I wouldn't do that!

12
00:10:03,566 --> 00:10:07,047
-Shit, that's not enough!
-Pull her back!

В настоящее время я использую этот шаблон, но он забывает все две строки текста.

(?<Order>\d+)\r\n(?<StartTime>(\d\d:){2}\d\d,\d{3}) --> (?<EndTime>(\d\d:){2}\d\d,\d{3})\r\n(?<Sub>.+)(?=\r\n\r\n\d+|$)

Любая помощь приветствуется.

Это было полезно?

Решение

Я думаю, что с регулярным выражением есть две проблемы.Первое заключается в том, что . ближе к концу в (?<Sub>.+) не соответствует символу новой строки.Таким образом, вы можете изменить его на:

(?<Sub>(.|[\r\n])+?)

Или вы можете указать RegexOptions.Singleline как вариант регулярного выражения.Единственное, что делает этот параметр, — это соответствие точек новой строке.

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

(?<Sub>(.|[\r\n])+?(?=\r\n\r\n|$))

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

Другие советы

На вашем месте я бы отошел от реализации на основе регулярных выражений и посмотрел на конечный автомат, просматривающий файл построчно.Ваш формат выглядит достаточно простым, чтобы справиться с 20-40 строками простого для понимания кода, но слишком сложен для разумного регулярного выражения.

Я бы лично разделил строки на массив и просматривал бы массив, проверяя каждую строку, просто выполняя регулярное выражение для строк StartTime->EndTime, затем вы можете использовать довольно простую логику, чтобы получить Order из предыдущей строки и получить текст из следующих строк (путем поиска вперед, чтобы найти следующее время начала-> время окончания и возврата на две строки).

Я думаю, что этот способ немного упрощает проблему, и у вас не будет регулярного выражения, пытающегося сделать все это.

Я использую следующее регулярное выражение для анализа файлов .srt:

@"(?<number>\d+)\r\n(?<start>\S+)\s-->\s(?<end>\S+)\r\n(?<text>(.|[\r\n])+?)\r\n\r\n"

Язык регулярных выражений — краткий справочник

Я использовал это регулярное выражение в своем парсере Ruby:

slines.scan(/(^[0-9]+)\r?\n(.*? --> .*?)\r?\n(.*?)(?=^[0-9]+\r?\n|\s+\Z)/im).map{|z| [z[0],[z[1],z[2].strip]]}

где «slines» — весь файл субтитров, считанный в память.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top