Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Regex 在Perl中有选择地拆分字符串_Regex_Perl_Parsing_Split - Fatal编程技术网

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

Regex 在Perl中有选择地拆分字符串,regex,perl,parsing,split,Regex,Perl,Parsing,Split,Perl新手 我需要分析如下所示的报告: 2012-05-29@emaillocalpart@emaildomain@customerid@errormessage@messageid 我用过: my @fields = split(/@/, $line, 6); 大多数情况下,它工作正常,但有时错误消息将包含电子邮件地址和该电子邮件上@符号后的所有文本,直到字符串的结尾将在我的邮件id上结束 我想检查@s的数量并进行条件解析,但是有更好的方法吗 编辑: 所需的输出是字符串列表,错误消息包含

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
在解析第2行之后:

2012-05-29
foobar
invalid.com
ZZ88-6
550 5.1.1 <foobar@invalid.com>... User Unknow
GGH93
2012-05-29
福巴
无效的.com
ZZ88-6
550 5.1.1 ... 用户未知
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
$str='5-29@foobar@无效。com@ZZ88-6@550 5.1.1 ... 使用者Unknow@GGH93';
#$str='2012-05-29@joedoe@例如。com@AB99-5@4404.4.1一些错误occurred@XYZ35';
$str=~s/(\]+\>)/!!/;#将电子邮件地址替换为!!
$email=$1;#存储电子邮件
@字段=拆分(/@/,$str);#分开@
s//$电子邮件/foreach(@fields);#找到旧的!!并替换为电子邮件地址
打印标准映射{“$\un”}@fields;#将字段打印到标准错误

看到它工作。这假设您只有一封可选电子邮件。只需稍加修改,它就可以用于包含任意数量的
分隔电子邮件的字符串。

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

my $re = '^' . '([^@]*)@'x4 . '(.*)@([^@]*)$';
my @fields = $line =~ /$re/; 
您可能还想在此处执行一些错误检查:

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

你能澄清你想要的输出是什么吗?字符串列表?设计起来有点困难,因为分隔符可能是数据的一部分。如果您有权访问报表生成器,我会考虑转义错误消息或更改分隔符字符…您能否给出一个带有电子邮件地址的特殊错误消息的示例?您是否将带有
@
的行存储在脚本的变量中?请澄清您的错误,可能是
字段的内容。
。请稍候,您想要错误消息吗??请尽可能清楚地写下你的答案。OP的问题是:“因为有其他应用程序使用同一个报表,所以我无法更改分隔符或转义输出。”刚刚测试过,效果很好,尽管我的真实报表有16个字段,而不是6个字段,所以一行代码看起来会有点难看。:)@CleberGoncalves我的答案适用于任意数量的字段,没有繁琐的正则表达式。仅供参考:-)注意:我有一个错误,我的目的是将两个电子邮件部分解析为一个标记,因此我们程序的输出现在不同了。@daxim,但这似乎是期望的结果,至少如问题示例所示。选择此解决方案是因为它最容易应用于我的特定问题,并且正则表达式看起来很清楚。在此处运行示例:编辑了我的问题,在尝试您的解决方案时,我发现报告中可能还包含未用分隔符分隔的电子邮件地址。错误消息几乎是免费文本。将与正则表达式一起使用。
my @fields = $line =~ /$re/ or die "can't parse '$line'";