繁体   English   中英

在Perl中有选择地拆分字符串

[英]Selectively splitting a string in Perl

Perl新手。

我需要解析一个如下所示的报告:

2012-05-29@emaillocalpart@emaildomain@customerid@errormessage@messageid

我用了:

my @fields = split(/@/, $line, 6);

大部分时间它工作正常,但有时错误消息将包含一个电子邮件地址和该电子邮件上的@符号后面的所有文本,直到字符串的结尾将以我的消息ID结束。

我考虑过检查@s的数量并进行条件解析,但是有更好的方法吗?

编辑:

所需的输出是一个字符串列表,错误消息包含其中包含的内容(包括偶尔的电子邮件地址)。

由于有其他应用程序使用相同的报告,我无法更改分隔符或转义输出。

报告中的示例行:

2012-05-29@joedoe@example.com@AB99-5@440 4.4.1 Some error occurred@XYZ35
2012-05-29@foobar@invalid.com@ZZ88-6@550 5.1.1 <foobar@invalid.com>... User Unknow@GGH93
2012-05-29@barfoo@invalid.com@YY88-0@550 5.1.1 barfoo@invalid.com no such user@GGH93

解析第1行后@fields的预期内容:

2012-05-29
joedoe
example.com
AB99-5
440 4.4.1 Some error occurred
XYZ35

解析第2行之后:

2012-05-29
foobar
invalid.com
ZZ88-6
550 5.1.1 <foobar@invalid.com>... User Unknow
GGH93

如果$ teststr包含,例如:'2012-05-29 @ emaillocalpart @ emaildomain @ customerid @ error @ me @ssage @ messageid';

以下代码:

my @fields2=split('@',$teststr);
my @finalfields=@fields2[0 .. 3];
my $finalat=$#fields2-1;
my $errormessage=join('@',@fields2[4 .. $finalat]);
push(@finalfields,$errormessage);
push(@finalfields,$fields2[$#fields2]);

print Data::Dumper->Dump([@finalfields])."\n";

给出以下输出:

$VAR1 = '2012-05-29';
$VAR2 = 'emaillocalpart';
$VAR3 = 'emaildomain';
$VAR4 = 'customerid';
$VAR5 = 'error@me@ssage';
$VAR6 = 'messageid';

道歉 - 这是一个冗长的解决方案。 您也可以在一个正则表达式中执行相同的操作:

$teststr=~/(.[^@]*)@(.[^@]*)@(.[^@]*)@(.[^@]*)@(.*)@(.[^@]*)/;
print "$1\n$2\n$3\n$4\n$5\n$6\n";

这会正确解析可选的电子邮件地址:

$str = '5-29@foobar@invalid.com@ZZ88-6@550 5.1.1 <foobar@invalid.com>... User Unknow@GGH93';
#$str= '2012-05-29@joedoe@example.com@AB99-5@440 4.4.1 Some error occurred@XYZ35';

$str =~ s/(\<[^\>]+\>)/!!/; # replace an email address with !!
$email = $1; # store the email

@fields = split(/@/,$str); # split on @

s/!!/$email/ foreach (@fields); # find the old !! and replace with the email address

print STDERR map { "$_ \n" } @fields; # print fields to standard error

看到它在这里工作。 这假设您只有一个可选的电子邮件。 通过一些工作,它可以被修改为适用于包含任意数量< >分隔的电子邮件的字符串。

类似于daxim的答案,但另一种写作方式:

my $re = '^' . '([^@]*)@'x4 . '(.*)@([^@]*)$';
my @fields = $line =~ /$re/; 

您可能还想在此处执行一些错误检查:

my @fields = $line =~ /$re/ or die "can't parse '$line'";

处理这个问题的最简单方法是将@更改为另一个非常不常见的分隔符,例如;;;;

暂无
暂无

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

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