在Perl中使用正则表达式拆分字符串

时间:2015-07-20 15:10:02

标签: regex perl

我需要帮助将以下字符串拆分为(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;

6 个答案:

答案 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";