1

我正在做一个项目,由于一个简单但非常不幸的错误,需要在文件中重写一堆时间戳;具体来说,我需要将每个时间戳的最后一部分除以 30。例如,如果文件包含:

"blahblahblah[00:05:25]randomblah[01:22:13]"

那我需要它说

"bahblahblah[00:05:833]randomblah[01:22:433]"

在意识到纯正则表达式无法处理问题后,因为它只处理字符而不是数字,一点点谷歌搜索将我指向 Perl 单行,我正在尝试对其进行修改以适应我的目的。这是我到目前为止所拥有的:

perl -pi.bak -e 's/\d\d:\d\d:($1/30)!/e

但是,我有一个语法错误"around /30"。任何人都可以帮助解决这个问题,并阐明它是如何工作的吗?我得到了逐行的东西,但不是表达部分。谢谢!

4

2 回答 2

0

您可以使用备用分隔符,例如s!!!. 您需要 2 个捕获组:一个用于小时:分钟,另一个用于修改后的秒数。您需要使用g修饰符来更改一行上的所有实例。请参阅perlop 中的 s/PATTERN/REPLACEMENT/

use warnings;
use strict;

$_ = 'blahblahblah[00:05:25]randomblah[01:22:13]';
s!(\d{2}:\d{2}:)(\d{2})!$1 . int(1000*$2/30)!ge;
print "$_\n";

__END__

blahblahblah[00:05:833]randomblah[01:22:433]
于 2014-07-22T18:27:27.683 回答
0

您提出的解决方案

perl -pi.bak -e 's/\d\d:\d\d:($1/30)!/e

由于多种原因不起作用;主要是您的替换s///没有两个正确的参数。从表面上看,您想替换与 匹配\d\d:\d\d:($1的内容30)!

我不清楚你所说的感叹号是什么意思!,但我认为你的意图更像是

perl -pi.bak -e 's{(\d\d:\d\d:)(\d\d)}{$1.$2/30}eg'

它保存并恢复前两个字段并将第三个字段除以 30。不幸的是,这并不完全正确,因为它给了你

97blahblahblah[00:05:0.833333333333333]randomblah[01:22:0.433333333333333]

与您的样本数据。

因此,您需要除以 30 后的商的前三位。如果您想要最接近的整数并且您有一个相当新的 Perl 版本,那么这个单行解决方案应该适合您。它将修改后的文本打印到 STDOUT。如果您想就地修改文件,则可以添加-i.bak为您自己的版本。

perl -pe's{\d\d:\d\d:\K(\d\d)}{sprintf "%.0f", $1/30*1000}ge' myfile
于 2014-07-22T19:45:32.537 回答