编辑文本/srt 文件

编辑文本/srt 文件

我有一个像这样的 .srt 文件

输入文件

1
00:00:17,920 --> 00:00:21,159
The essential is invisible to the eye. 3

2
00:00:21,160 --> 00:00:22,559
This phrase comes from 4

3
00:00:22,560 --> 00:00:25,039
As if saying goodbye saddens me, 5

您可以看到每个对话后都有一个数字(例如 '...eye.' 后为 3,'...from' 后为 4)。我想删除这些数字。

预期输出文件

1
00:00:17,920 --> 00:00:21,159
The essential is invisible to the eye.

2
00:00:21,160 --> 00:00:22,559
This phrase comes from

3
00:00:22,560 --> 00:00:25,039
As if saying goodbye saddens me,

有什么聪明的方法可以删除这些号码吗?我使用的是 Ubuntu 22.04。

答案1

使用GNU awk

$ awk '/\s+[0-9]+\s*$/{NF--}1'
$ awk '{sub(/[[:space:]]+[0-9]+[[:space:]]*$/,"")}1'

或者

$ awk '/[[:alpha:]]+/ && $NF ~ /^[[:digit:]]+$/{$NF=""}1' file

答案2

在每个 Unix 机器上的任何 shell 中使用任何 sed:

$ sed 's/ [0-9]*$//' file
1
00:00:17,920 --> 00:00:21,159
The essential is invisible to the eye.

2
00:00:21,160 --> 00:00:22,559
This phrase comes from

3
00:00:22,560 --> 00:00:25,039
As if saying goodbye saddens me,

如果您愿意,您可以对任何 awk 执行相同的操作:

awk '{sub(/ [0-9]*$/,"")}1' file

我只使用了 OP 示例输入的前 3 个块进行测试,因为输入的其余部分基本相同,因此只会使示例变得混乱。

答案3

Perl

输入文件:

1
00:00 --> 00:00
foo bar 10
    
2
00:00 --> 00:00
base qux 11
    
3
00:00 --> 00:00
aqw zdv 12

命令:

Perl --version>= 5.36:

perl -g -pe 's/\d+(?=\n\s*\n)//g' file

Perl --version< 5.36:

perl -0777 -pe 's/\d+(?=\n\s*\n)//g' file

输出:

1
00:00 --> 00:00
foo bar 

2
00:00 --> 00:00
base qux 

3
00:00 --> 00:00
aqw zdv 

正则表达式匹配如下:

节点 解释
\d+ 数字 (0-9)(1 次或多次(匹配尽可能多的数量))
(?= 展望看看是否有:
\n '\n'(换行符)
\s* 空格(\n、\r、\t、\f 和 " ")(0 次或多次(匹配尽可能多的数量))
\n '\n'(换行符)
) 前瞻结束

答案4

使用(以前称为 Perl_6)

~$ raku -e 'for slurp() { print S:g/ \s* \d+ <?before \n\s*\n > //};'  file

#OR:

~$ raku -e 'print S:g/ \s* \d+ <?before \n\s*\n > // for slurp();'  file

上面是用 Raku(Perl 编程语言家族的成员)编写的答案。基本上我已经用 Raku 重写了 @GillesQuénot 的优秀 Perl 答案。 Raku 有一个功能slurp,可以让您一次将整个文件读入内存,保留\n换行符等(类似于 Perl 的-0777命令行选项)。然后很容易使用 Raku 版本的正向前瞻,这里拼写为<?before \n\s*\n >(Raku 是空白容忍的,所以你可以隔开正则表达式原子)。

人们常常对替换运算符的返回值感到困惑。 Raku 采取了提供“big-S”S///运营商的方式,返回结果字符串。另外,应该注意的是,在 Raku 中,正则表达式修饰符如:global:g位于运算符的前面,而不是像 Perl 中那样位于后面。

注意:在不了解有关.srt文件规范的更多信息的情况下,使用 Raku<?before [\n\s*\n | \n$] >前瞻可能更安全,即使它们是行,它也会正确编辑行\n文件的最后一个完整终止行(感谢@tink 在评论中指出这个问题)。

输入示例:

1
00:00 --> 00:00
foo bar 10

2
00:00 --> 00:00
base qux 11

3
00:00 --> 00:00
aqw zdv 12

示例输出:

1
00:00 --> 00:00
foo bar

2
00:00 --> 00:00
base qux

3
00:00 --> 00:00
aqw zdv

Raku 中的另一种方法是使用<( … )>捕获标记:

~$ raku -e 'for slurp() { print S:g/ <( \s* \d+ )> \n\s*\n //};'  file

#OR:

~$ raku -e 'print S:g/ <( \s* \d+ )> \n\s*\n // for slurp();'  file

如果不了解更多关于目标文件的信息,就很难提出进一步的方法。 Perl 有一个“段落模式”,可以用.split(/ \n ** 2..* /).如果每个“段落”都是 3 行,那么 Raku 就具有rotorbatch它们视为一个单元的功能。 Raku 还为不太规则的段落提供了“触发器”运算符。请参阅下面的链接了解起点。

https://docs.raku.org/language/regexes
https://docs.raku.org/language/regexes#Capture_markers:_%3C(_)%3E
https://raku.org

相关内容