我有一个像这样的 .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 就具有rotor
将batch
它们视为一个单元的功能。 Raku 还为不太规则的段落提供了“触发器”运算符。请参阅下面的链接了解起点。
https://docs.raku.org/language/regexes
https://docs.raku.org/language/regexes#Capture_markers:_%3C(_)%3E
https://raku.org