gpt4 book ai didi

perl - 在 perl 中解析字符串的最佳方法

转载 作者:行者123 更新时间:2023-12-05 01:35:41 25 4
gpt4 key购买 nike

为了完成下面的任务,我在 C 下编写了类似 perl 的程序(因为我是 Perl 的新手),但我不确定这是否是最好的实现方式。

有人可以指导吗?注意:不是完整的程序,而是我可以改进的地方。

提前致谢

输入:

$str = "mail1, local<mail1@mail.local>, mail2@mail.local, <mail3@mail.local>, mail4 local<mail4@mail.local>"

预期输出:

mail1, local<mail1@mail.local>
mail2@mail.local
<mail3@mail.local>
mail4, local<mail4@mail.local>

示例程序

my $str="mail1, \@local<mail1\@mail.local>, mail2\@mail.local, <mail3\@mail.local>, mail4, local<mail4\@mail.local>";
my $count=0, @array, $flag=0, $tempStr="";
for my $c (split (//,$str)) {
if( ($count eq 0) and ($c eq ' ') ) {
next;
}
if($c) {
if( ($c eq ',') and ($flag eq 1) ) {
push @array, $tempStr;
$count=0;
$flag1=0;
$tempStr="";
next;
}
if( ($c eq '>' ) or ( $c eq '@' ) ) {
$flag=1;
}
$tempStr="$tempStr$c";
$count++;
}
}
if($count>0) {
push @array, $tempStr;
}
foreach my $var (@array) {
print "$var\n";
}

编辑:

输入:

Input is the output of above code.

预期输出:

"mail1, local"<mail1@mail.local>
"mail4, local"<mail4@mail.local>

示例代码:

$str =~ s/([^@>]+[@>][^,]+),\s*/$1\n/g;
my @addresses = split('\n',$str);
if(scalar @addresses) {
foreach my $address (@addresses) {
if (($address =~ /</) and ($address !~ /\"/) and ($address !~ /^</)){
$address="\"$address";
$address=~ s/</\"</g;
}
}
$str = join(',',@addresses);
}
print "$str\n";

最佳答案

如我所见,您想替换每个:

  • 逗号和后面的空格,
  • 发生在 @ 之后或 > ,

换行。

要进行这样的替换,您可以使用一个正则表达式。

搜索部分可以如下:

([^@>]+[@>][^,]+),\s*

详细信息:

  • ( - 第一个捕获组开始。
    • [^@>]+ - 除 @ 之外的非空字符序列或 > .
    • [@>] - @> .
    • [^,]+ - 除逗号外的非空字符序列。
  • ) - 第一个捕获组结束。
  • ,\s* - 逗号和可选的空格序列。

替换部分应该是:

  • $1 - 第一捕获组。
  • \n - 换行符。

所以整个程序,比你的短得多,可以如下所示:

my $str='mail1, local<mail1@mail.local>, mail2@mail.local, <mail3@mail.local>, mail4, local<mail4@mail.local>';
print "Before:\n$str\n";
$str =~ s/([^@>]+[@>][^,]+),\s*/$1\n/g;
print "After:\n$str\n";

为了替换所有需要的逗号,我使用了g选项。

请注意,我将源字符串放在 引号中,否则 Perl会提示可能意外插入@mail

编辑

您修改后的要求必须以不同的方式处理。“普通”更换不是一种选择,因为现在有一些要匹配的片段和要忽略的一些框架。

所以基本思路是写一个while使用匹配正则表达式循环: (\w+),?\s+(\w+)(<[^>]+>) , 意思是:

  • (\w+) - 第一个捕获组 - 一系列单词字符(例如 mail1 )。
  • ,?\s+ - 可选的逗号和一系列空格。
  • (\w+) - 第二个捕获组 - 一系列单词字符(例如 local )。
  • (<[^>]+>) - 第三个捕获组 - 除 > 之外的一系列字符(实际邮件地址),用尖括号括起来,例如<mail1@mail.local> .

在循环的每次执行中,您都可以访问组在此特定匹配项中捕获($1$2、...)。

所以这个循环的内容就是打印所有这些捕获的组,需要额外的字符。

代码(同样比你的短得多)应该如下所示:

my $str = 'mail1, local<mail1@mail.local>, mail2@mail.local, <mail3@mail.local>, mail4 local<mail4@mail.local>';
while ($str =~ /(\w+),?\s+(\w+)(<[^>]+>)/g) {
print "\"$1, $2\"$3\n";
}

关于perl - 在 perl 中解析字符串的最佳方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50746340/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com