正则表达式匹配双语字幕文本

时间:2018-01-17 12:01:17

标签: php regex

我一直在乱用正则表达式,并且不能有效地找到这个文本。我确定专家会马上知道。

基本上我需要这样做:

3
00:00:45,607 --> 00:00:49,202
<i>Good morning,
it's GLR Breakfast on 94.9 FM...</i>
早上好,这里是调频94.9 GLR早餐电台

4
00:00:54,727 --> 00:00:56,319
Wha...?!
什么?

5
00:01:03,527 --> 00:01:05,722
Oh, no!
噢, 不

6
00:01:16,207 --> 00:01:20,564
<i>Don't go back to sleep,
you lazy sowI It's 8 o'clockI</i>
你敢睡回笼觉,已经八点了你个懒鬼

7
00:01:20,727 --> 00:01:24,766
<i>You've got three seconds
before the saucepan lidsI</i>
在锅铲乐前你还有三秒

8
00:01:28,447 --> 00:01:31,644
Oh, yes! All right!
好吧,好吧

进入这个:

3
00:00:45,607 --> 00:00:49,202
早上好,这里是调频94.9 GLR早餐电台

4
00:00:54,727 --> 00:00:56,319
什么?

5
00:01:03,527 --> 00:01:05,722
噢, 不

6
00:01:16,207 --> 00:01:20,564
你敢睡回笼觉,已经八点了你个懒鬼

7
00:01:20,727 --> 00:01:24,766
在锅铲乐前你还有三秒

8
00:01:28,447 --> 00:01:31,644
好吧,好吧

我知道中文文本可以与{Han}匹配,但在这里我需要&#39;不是&#39;匹配它或它与时间索引之间的匹配,但我不能让它工作得很好。特别是因为有些线路是多个而有些不是......

4 个答案:

答案 0 :(得分:2)

假设格式为 Number,Linebreak,Timestamp - &gt;时间戳,Linebreak,1 +英文行,1 +中文行可以使用

(\d+\R\d{2}:\d{2}:\d{2},\d+ --> \d{2}:\d{2}:\d{2},\d+\R)\P{Han}+

并替换为$1

捕获组用于通过已知标题导航到正确的位置,然后\P{Han}匹配非中文的所有内容。

如果中文也可以从数字等开始,您可以使用(?:(?!.*\p{Han}).*\R)+代替\P{Han}来匹配所有不包含任何中文字符的行。

您也可以使用\K重置匹配内容,然后使用空替换,而不是捕获组。为此,请将模式的第一部分更改为\d+\R\d{2}:\d{2}:\d{2},\d+ --> \d{2}:\d{2}:\d{2},\d+\R\K

另见https://regex101.com/r/FaEwrb/1/

答案 1 :(得分:1)

您可以使用

(^\d+\R
\d{2}:.+\R)
(?:(?!.*\p{Han}).+\R?)*
((?:.+\R?)+)

并将其替换为$1$2,请参阅a demo on regex101.com

<小时/> 细分,这说:

(^\d+\R                  # capture into group 1, start of line, digits and a linebreak
\d{2}:.+\R)              # two digits, : and anything in that line afterwards
(?:(?!.*\p{Han}).+\R?)*  # match (but don't capture) any line where no char of \p{Han} is
((?:.+\R?)+)             # capture the rest into group 2

答案 2 :(得分:0)

我并不是说这在任何方面都是完美的,但它适用于此示例案例,也可能适用于其他示例。

如果有超过三个&#34;英文字母&#34;我会在时间下面检查每一行。如果它我删除它。
当然这可能是问题的根源,但你必须决定它是否是一个问题。

$arr =explode(PHP_EOL.PHP_EOL, $t);

Foreach($arr as &$group){
    $lines = explode(PHP_EOL, $group);
    For($i=2;$i<count($lines);$i++){//I=2 is line three, just below timestamp
        If(preg_match("/[a-zA-Z \.,?!]{3,}/", $lines[$i])){
            unset($lines[$i]);
        }
    }
    $group = implode(PHP_EOL, $lines);
}
Echo implode(PHP_EOL.PHP_EOL, $arr);
请原谅我的中文,我只是想用更多的线来扩展测试,看它是否仍然有用。

https://3v4l.org/5bk7I

答案 3 :(得分:0)

以下表达式匹配示例

中的所有必需行
(?:.*\p{Han}.*)+|(?:\d{2}:\d{2}:\d{2},\d{3}(?: --> )?)+|^\d+$

使用的标志是全局和多行的;

<强>解释

(?:.*\p{Han}.*)+必须至少包含一个中文字符

(?:\d{2}:\d{2}:\d{2},\d{3}(?: --> )?)+匹配时间戳

^\d+$匹配索引

Test it here