使用模式将文本分隔成单独的元素 - javascript

Seperating text into separate elements using a pattern - javascript

提前为我糟糕的代码道歉/试图解释我想要实现的目标...

我想获取带有时间戳的各种文字记录,并将其转换为一致的格式以创建字幕。抄本来源不同,文档结构和时间戳各不相同,有时甚至在同一文档中。

时间戳的格式是[HH:MM:SS.FF](我可以处理的变化),它包含在文本中。并且时间戳 有时 指示和结束点(通常它们只是起点)。

所以格式是

[Timestamp1]Some text with various line breaks and weird characters.
[Timestamp2]More text where this transcript continues but ends with some silence after this
[Timestamp3]
[Timestamp4]The next sentence begins and ends at the last
[Timestamp5]

在 JavaScript 中最好的编码方法是什么?我已经用 string.split 和 re.matchAll 绕过房子,但是 none 我想出的正则表达式模式可以连续处理 2 个时间戳。

我认为理想情况下我会使用获取时间戳的正则表达式模式,然后存储具有开始和结束时间戳的对象数组(如果结束不存在,则结束是下一个开始)和相关文本。

所以对于上面的例子我会

Start: Timestamp1 End: Timestamp2 Text: "Some text..."

Start: Timestamp2 End: Timestamp3 Text: "More text..."

Start: Timestamp4 End: Timestamp5 Text: "The next..."

这是我最近的尝试之一...

function test(){
        str = 
        `[09:35:10.00]
        1. Lorem ipsum...
        [09:35:13.11]
        [09:35:15.14]
        2. sed do eiusmod...
        [09:35:39.20]
        3. anim id est laborum...
        [09:35:43.17]`

        var re = /(?<tc1>\[?(?:[0-1][0-9]|2[0-3]|[0-9]):(?:[0-5][0-9]):(?:[0-5][0-9])(?:\.(?:[0-9]{2,3})?\]?))\s*(.*)\s*(?<tc2>\[?(?:[0-1][0-9]|2[0-3]|[0-9]):(?:[0-5][0-9]):(?:[0-5][0-9])(?:\.(?:[0-9]{2,3})?\]?))?.*/gm;

        const matches = str.matchAll(re);
        for (const match of matches) {
                console.log(`Start TC:\n${match[1]}\nText:\n${match[2]}\nTC2:\n${match[3]}`);
        }
}

不幸的是,这不适合变化。

感谢任何正确方向的指点。

图案需要由3部分组成:

  • 匹配并捕获时间戳:[,后跟数字、冒号和句点:\[\d{2}:\d{2}:\d{2}\.\d{2}\]
  • 匹配并捕获时间戳以外的任何字符:(?:(?!TIMESTAMP).)+ 其中 TIMESTAMP 是上面的模式
  • 向前看并捕获时间戳:只需使用上面的时间戳模式

您必须提前查找时间戳而不是正常匹配它,因为有问题的时间戳可能需要成为 下一个 匹配的一部分。

放在一起,你得到:

str =
  `[09:35:10.00]
        1. Lorem ipsum...
        [09:35:13.11]
        [09:35:15.14]
        2. sed do eiusmod...
        [09:35:39.20]
        3. anim id est laborum...
        [09:35:43.17]`

var re = /(\[\d{2}:\d{2}:\d{2}\.\d{2}\])((?:(?!\[\d{2}:\d{2}:\d{2}\.\d{2}\]).)+)(?=(\[\d{2}:\d{2}:\d{2}\.\d{2}\]))/gs;

const matches = str.matchAll(re);
for (const match of matches) {
  console.log(`Start TC:\n${match[1]}\nText:\n${match[2]}\nTC2:\n${match[3]}`);
}

或者,commenting the regex

const pattern = makeExtendedRegExp(String.raw`
( # First capture group: timestamp
  \[\d{2}:\d{2}:\d{2}\.\d{2}\]
)
( # Second capture group: text
  (?:(?!
    # Timestamp pattern again:
    \[\d{2}:\d{2}:\d{2}\.\d{2}\]
  ).)+
)
(?=( # Look ahead for and capture the timestamp in 3rd group:
  # Timestamp pattern again:
  \[\d{2}:\d{2}:\d{2}\.\d{2}\]
))
`, 'gs');



function makeExtendedRegExp(inputPatternStr, flags) {
  const cleanedPatternStr = inputPatternStr
    .replace(/(^|[^\]) *#.*/g, '')
    .replace(/^\s+|\s+$|\n/gm, '');
  return new RegExp(cleanedPatternStr, flags);
}


str =
  `[09:35:10.00]
        1. Lorem ipsum...
        [09:35:13.11]
        [09:35:15.14]
        2. sed do eiusmod...
        [09:35:39.20]
        3. anim id est laborum...
        [09:35:43.17]`

const matches = str.matchAll(pattern);
for (const match of matches) {
  console.log(`Start TC:\n${match[1]}\nText:\n${match[2]}\nTC2:\n${match[3]}`);
}