繁体   English   中英

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

[英]Splitting a string using regex in 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;

好。 这种分裂只是不起作用 - 因为你使用了单引号,字符串是按字面意思使用的。 由于它不会出现在示例文本中,因此根本不会执行任何操作。

拆分“切断”基于字段分隔符的字符串,这可能不是您想要的。 例如

 split ( ' ', $data ); 

会给你:

$VAR1 = [
          'May',
          '26',
          '09:33:33',
          'localhost',
          'archiver:',
          'saving',
          'ID',
          '0091070818_1432647213_489715',
          'took',
          '180',
          'msec'
        ];

鉴于你的字符串没有像这样正确地“字段化”,我建议采用不同的方法:

你需要从中选择你想要的东西。 假设你没有得到一些奇怪的记录混合:

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))

甚至可能最简单的方法是将数据拆分为空格(然后通过将前三个字段连接在一起来重建日期)。 它不是很复杂,但它完成了工作。

#!/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

split看起来不像是工作的正确工具。 我使用正则表达式匹配:

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

我不知道split()是最好的方法。 此代码与您的目标ID匹配并提取它:

($id) = $data =~ m/(?<=ID )[^_]+/g;

正则表达式使用后视(?<=ID )将匹配的开始锚定在"ID "的右侧,然后抓取所有内容而不是下面的下划线。


这是一些测试代码:

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

查看现场演示

最好用三种不同的模式来做到这一点。 下面的代码演示了

我使用了/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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM