为了实现以下任务,我在下面写了类似于perl程序的C(因为我是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";
答案 0 :(得分:2)
如我所见,你想要替换每一个:
@
或>
之后,换行。
要进行此类替换,您可以使用,而不是编写解析程序 一个正则表达式。
搜索部分如下:
([^@>]+[@>][^,]+),\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";
}
答案 1 :(得分:1)
这是一种使用split的方法,在这种情况下还需要一个仔细的正则表达式
use warnings;
use strict;
use feature 'say';
my $string = # broken into two parts for readabililty
q(mail1, local<mail1@mail.local>, mail2@mail.local, )
. q(<mail3@mail.local>, mail4, local<mail4@mail.local>);
my @addresses = split /@.+?\K,\s*/, $string;
say for @addresses;
split
在其分隔符规范中采用完整的正则表达式。在这种情况下,我认为每条记录都是以电子邮件地址后面的逗号分隔的,因此@.+?,
只有在模式开头之前匹配模式时才会想到逗号之前的negative lookbehind。但那些长度不可变,这正是这里的情况。
我们通常可以匹配模式@.+?
,然后使用\K
form(lookbehind)删除所有先前的匹配,以便它们不会从字符串中取出。因此,当,\s*
前面有电子邮件地址@...
(未消费的内容)时,上面会在mail1, local<mail1@mail.local>
mail2@mail.local
<mail3@mail.local>
mail4, local<mail4@mail.local>
上拆分。
打印
<...>
编辑询问引用my @addresses = split /@.+?\K,\s*/, $string; #/ stop syntax highlight
s/(.+?,\s*.+?)</"$1"</ for @addresses;
say for @addresses;
之前的描述。一种简单的方法是,一旦从字符串中解析出地址,就进行另一次传递。例如
$_
循环中的正则表达式是更改数组元素的一种方法。我使用它来提高效率(改变元素),简洁,并作为以下属性的演示。
在foreach loop索引变量(或foreach my $elem (@addresses) {
$elem =~ s/(.+?,\s*.+?)</"$1"</;
}
)是当前处理的元素的别名 - 因此更改它会更改该元素。这是在不知不觉中允许的已知错误来源,这是以上述形式显示它的另一个原因。
该陈述也使用statement modifier,它等同于
foreach
这通常被认为是一种更恰当的写作方式,但我发现另一种形式更清楚地强调了元素的改变,而这只是$file_path = $target_dir.$newfilename;
$cFile = curl_file_create($file_path);
$data = array(
"file" => $cFile,
);
$target_url = "https://filedrop.gfycat.com";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $target_url);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
"Content-Type: multipart/form-data"
));
$response = curl_exec($ch);
var_dump($response); // bool(false) here
curl_close($ch);
的唯一目的。