Регулярное выражение, соответствующее всему файлу - PullRequest
1 голос
/ 17 апреля 2019

У меня есть большой файл SRT (субтитры), который я пытаюсь преобразовать в JSON, но мое регулярное выражение работает неправильно.

Мое выражение:

^(\d+)\r?\n(\d{1,2}:\d{1,2}:\d{1,2}([.,]\d{1,3})?)\s*\-\-\>\s*(\d{1,2}:\d{1,2}:\d{1,2}([.,]\d{1,3})?)\r?\n([\s\S]*)(\r?\n)*$

Вот пример моего файла srt, каждый субтитр следует той же схеме.

1
00:00:11,636 --> 00:00:13,221
Josh communicated but

2
00:00:13,221 --> 00:00:16,850
it's also the belief that
we never knew the severity

мой файл javascript

const fs = require('fs');
function parse(content, options) {
    var captions = [];
    var parts = content.split(/\r?\n\s+\r?\n/g);
    for (var i = 0; i < parts.length; i++) {
        var regex = /^(\d+)\r?\n(\d{1,2}:\d{1,2}:\d{1,2}([.,]\d{1,3})?)\s*\-\-\>\s*(\d{1,2}:\d{1,2}:\d{1,2}([.,]\d{1,3})?)\r?\n([\s\S]*)(\r?\n)*$/gi;
        var match = regex.exec(parts[i]);
        if (match) {
            var caption = {};
            var eol = "\n";
            caption.id = parseInt(match[1]);
            caption.start = match[2];
            caption.end = match[4];
            var lines = match[6].split('/\r?\n/');
            caption.content = lines.join(eol);
            captions.push(caption);
            continue;
        }
    }
    return captions;
};

var content = fs.readFileSync('./English-SRT-CC.srt', 'utf8');
var captions = parse(content);
var json = JSON.stringify(captions, " ", 2);
console.log(json);
fs.writeFile("output.json", json, 'utf8', function (err) {
    if (err) {
        return console.log(err);
    }

    console.log("JSON file has been saved.");
});

И наконец, вот мой вывод:

{
    "id": 1,
    "start": "00:00:11,636",
    "end": "00:00:13,221",
    "content": "Josh communicated but\n\n2\n00:00:13,221 --> 00:00:16,850\n
// cut for shortness, it just continues the rest of the file inside "content"

Мой желаемый результат?

{
    "id": 1,
    "start": "00:00:11,636",
    "end": "00:00:13,221",
    "content": "Josh communicated but"
},
{
    "id": 2,
    "start": "00:00:13,221",
    "end": "00:00:16,850",
    "content": "it's also the belief that\n we never knew the severity"
}

Спасибо!

Редактировать: regex101

1 Ответ

4 голосов
/ 17 апреля 2019

Используйте это регулярное выражение для соответствия вашему тексту:

/\d+\n[0-9\:\,\-\>\s]{29}\n(.+|(\n[^\n]))+/g

Я разобью его на части:

Часть 1: \d+\n

Эта часть соответствует любым цифрам, за которыми следует ровно один символ новой строки.

Часть 2: [0-9\:\,\-\>\s]{29}\n

Эта часть соответствует включенным символам, точной длиной 29, что является фиксированным форматом, например, 00:00:11,636 --> 00:00:13,221, за которым следует один символ новой строки.

Часть 3: (.+|(\n[^\n]))+

Теперь эта часть важна. Я разобью его на части:

  • .+ соответствует любому символу, кроме символов новой строки.
  • (\n[^\n]) соответствует точно одному символу новой строки, за которым НЕ следует другой символ новой строки. Это важно для обеспечения возможности многострочного сопоставления субтитров. Без этого вы не сможете сопоставить многострочные субтитры (из-за структуры файла, а не из-за ограничения регулярных выражений).

Заключая их в скобки, (...)+ позволяет совпадать с несколькими строками. Вот как вы можете сопоставить многострочные субтитры.

Часть 4: g

Используйте это, чтобы соответствовать более чем 1 совпадениям.

Рабочий код

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

Вы можете увидеть, как вы можете его использовать:

const text = `
1
00:00:11,636 --> 00:00:13,221
Josh communicated but

2
00:00:13,221 --> 00:00:16,850
it's also the belief that
we never knew the severity
`;

const regex = /\d+\n+[0-9\:\,\-\>\s]{29}\n(.+|(\n[^\n]))+/g;
const rawResult = text.match(regex);

console.log(rawResult);

const parsedResult = rawResult.map(chunk => {
  const [id, time, ...lines] = chunk.split(/\n/g);
  const [start, end] = time.split(/\s\-\-\>\s/);
  const content = lines.join('\n');
  return { id, start, end, content };
});

console.log(parsedResult);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...