我需要帮助将以下字符串拆分为(Date,ID,msecs)
May 26 09:33:33 localhost archiver: saving ID 0191070818_1462647213_489705 took 180 msec
我只希望第一个下划线之前的ID的第一部分。
所以这就是我希望输出看起来像
May 26 09:33:33, 0191070818, 180
我无法弄清楚要在正则表达式中添加什么
use strict;
use warnings;
my $data = 'May 26 09:33:33 localhost archiver: saving ID 0091070818_1432647213_489715 took 180 msec';
my @values = split('/[]/', $data);
foreach my $val (@values) {
print "$val\n";
}
exit 0;
答案 0 :(得分:4)
行。这种分裂只是不起作用 - 因为你已经使用过单引号,字符串是按字面意思使用的。由于它没有出现在您的示例文本中,因此它根本不做任何事情。
分裂&#39>削减'一个基于字段分隔符的字符串,可能不是你想要的。例如。 split ( ' ', $data );
会给你:
$VAR1 = [
'May',
'26',
'09:33:33',
'localhost',
'archiver:',
'saving',
'ID',
'0091070818_1432647213_489715',
'took',
'180',
'msec'
];
鉴于你的字符串并没有真正实现' fieldify'正确地说,我建议采用不同的方法:
你需要从中选择你想要的东西。假设你没有得到一些奇怪的记录:
my $data = 'May 26 09:33:33 localhost archiver: saving ID 0091070818_1432647213_489715 took 180 msec';
my ($time_str) = ( $data =~ m/^(\w+ \d+ \d{2}:\d{2}:\d{2})/ );
my ($id) = ( $data =~ m/(\d+)_/ );
my ($msec) = ( $data =~ m/(\d+) msec/ );
print "$time_str, $id, $msec,\n";
注意 - 您可以组合正则表达式模式(如某些示例所示)。我已经这样做了,希望简化和澄清发生了什么。正则表达式匹配应用于$data
(因为=~
)。匹配'然后提取括号()
中的元素并返回'插入到左侧的变量中。
(注意 - 您需要在括号中包含' my($ msec)'因为这样使用的是值,而不是测试的结果(true / false))
答案 1 :(得分:4)
甚至可能最简单的方法是将数据拆分为空白(然后通过将前三个字段连接在一起来重建日期)。它不是很复杂,但它完成了工作。
#!/usr/bin/perl
use strict;
use warnings;
use 5.010;
my $data = 'May 26 09:33:33 localhost archiver: saving ID 0091070818_1432647213_489715 took 180 msec';
my @values = split(/\s+/, $data);
my $date = join ' ', @values[0,1,2];
my $id = $values[7];
my $time = $values[9];
say "Date: $date";
say "ID: $id";
say "Time: $time";
给出了:
Date: May 26 09:33:33
ID: 0091070818_1432647213_489715
Time: 180
答案 2 :(得分:3)
my @values = $data =~ /^([[:alpha:]]{3}\s[0-9][0-9]\s[0-9][0-9]:[0-9][0-9]:[0-9][0-9]) # date & time
\s.*?\sID\s
([0-9]+) # ID
.*\stook\s
([0-9]+) # duration
\smsec/x;
print join(',', @values), "\n";
看起来不像是工作的正确工具。我使用正则表达式匹配:
{{1}}
答案 3 :(得分:2)
我不知道split()
是最好的方法。此代码与您的目标ID匹配并提取它:
($id) = $data =~ m/(?<=ID )[^_]+/g;
正则表达式使用后视(?<=ID )
将匹配的开头锚定在"ID "
的右侧,然后抓取所有而不是后面的下划线。< / p>
这是一些测试代码:
my $data = 'May 26 09:33:33 localhost archiver: saving ID 0091070818_1432647213_489715 took 180 msec';
($id) = $data =~ m/(?<=ID )[^_]+/g;
print $id
输出:
0091070818
请参阅live demo。
答案 4 :(得分:2)
最好用三种不同的模式做到这一点。下面的代码演示了
我使用了/x
修饰符,这样我就可以在正则表达式中添加空格以提高可读性
除非您确定您的数据格式正确(即它是程序的输出),否则您应该添加测试以确保在模式匹配后所有三个值都定义。或者你可以直接测试模式匹配本身
use strict;
use warnings;
use v5.10;
my $s = 'May 26 09:33:33 localhost archiver: saving ID 0191070818_1462647213_489705 took 180 msec';
for ( $s ) {
my ($date) = / ^ ( [a-z]+ \s+ \d+ \s+ [\d:]+ ) /ix;
my ($id) = / ID \s+ (\d+) _ /x;
my ($msecs) = / (\d+) \s+ msec /x;
say join ',', $date, $id, $msecs;
}
May 26 09:33:33,0191070818,180
答案 5 :(得分:1)
split
不是此处使用的工具。这是一个正则表达式,至少适用于您列出的特定情况。
my $data = 'May 26 09:33:33 localhost archiver: saving ID 0091070818_1432647213_489715 took 180 msec';
$data =~ m/^(\w+ \d+ \d\d:\d\d:\d\d).+saving ID (\d+).+took (\d+) msec$/;
my ($date, $id, $msec) = ($1,$2,$3);
print "$date, $id, $msec\n";