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

Php 正则表达式匹配双语字幕中的文本,php,regex,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 --> 0

我已经和正则表达式混在一起很久了,不能让它有效地找到这个文本。我相信专家会马上知道的

基本上我需要这样做:

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!
好吧,好吧
我知道中文文本可以与
{Han}
匹配,但这里我需要“不”匹配它,或者匹配它与时间索引之间的匹配,但我无法让它完全正常工作。特别是因为有些行是多行的,有些行不是…

假设格式为数字、换行符、时间戳-->时间戳、换行符、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

另请参见您可以使用的

(^\d+\R
\d{2}:.+\R)
(?:(?!.*\p{Han}).+\R?)*
((?:.+\R?)+)
并将其替换为
$1$2
,请参阅。
分解后,这表示:

(^\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

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

我检查时间下面的每一行是否有三个以上的“英文字母”,如果有,我将其删除。
当然,这可能是问题的根源,但你必须决定这是否是一个问题

$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);
$arr=explode(PHP\u EOL.PHP\u EOL,$t);
Foreach($arr as和$group){
$lines=explode(PHP\u EOL,$group);

对于($i=2;$i),以下表达式匹配示例中所有必需的行

(?:.*\p{Han}.*)+|(?:\d{2}:\d{2}:\d{2},\d{3}(?: --> )?)+|^\d+$
使用的标志是全局和多行的

说明:

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

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

^\d+$
与索引匹配


您尝试过什么?这是StackOverflow每个问题的一个重要部分。@mickmackusa事实上并不总是如此。对于类似的问题,Regex可能最好不要这样做。对于Regex,您需要从头开始,尝试匹配您需要匹配的内容。对于代码块,它是不同的,并且您所说的内容适用。这就是为什么除了提到{Han}之外,我没有包括我尝试过的模式以防万一。提供您失败的尝试并没有什么丢脸的。它向我们展示了您在发布之前试图自行解决问题,这让我们有机会修复您的尝试,而不是为您编写新的代码。许多运营商使用免费编码服务,发布您的代码将您与这些用户区分开来。@mickmackusa我解释说我不会在第一句话中,ried说了很久了。我不是说你是个骗子,我只是恳请你向我们展示你失败的最佳尝试,这样我们就可以解释你陷入困境的原因和解决方法。+1很漂亮!但这些都是字幕,一切都是可能的。如果中文台词以数字开头怎么办?不需要捕获组/替换文本:I tho虽然这很完美,但S.Kablar是对的,如果中文文本以数字开头,它就不起作用了。@Hasen只需在@Sebastian Proske regex
的末尾添加
\R
(\d+\n[\d:,]+\S+-{2}\>\S+[\d:,]+\R)\P{Han}+\R
@mickmackusa当然,任何一种方法都是可能的(在我的答案中添加了这一点)哇,你把每一行都一一匹配了!真是太棒了。@Hasen:甚至当中文文本开头有数字时(请看第四条)。是的,我注意到了。这太完美了。
(?:.*\p{Han}.*)+|(?:\d{2}:\d{2}:\d{2},\d{3}(?: --> )?)+|^\d+$