我有一个包含许多名字的数组:
Fred Smith
Dave Davidson
John
Andy Wood
Robin van Persie
foreach my $name ( @arrayOfNames ) {
my ($first, $last) = $name =~ /(.*)\s+(.).*/;
print "$first$last";
}
使用上面显示的foreach循环,它应该打印以下内容:
FredS
DavidD
John
AndyW
RobinvP
但是,它没有正确处理一个单词名称(John)或两个以上的单词名称(Robin van Persie):
对于一个单词名称(John),我收到错误,如下所示
Use of uninitialized value $first in concatenation...
Use of uninitialized value $last in concatenation...
对于两个以上的单词名称(Robin van Persie),它打印Robin vanP
而不是RobinvP
如何更改以满足这一个单词和两个以上的单词名称? 是应该将一个单词和两个以上的单词名称移动到一个新的数组中然后再处理,还是可以改变正则表达式来满足这个要求?
答案 0 :(得分:5)
您可以使用split
代替正则表达式将名字与其他名称分开:
my ($first, @rest) = split;
my @initials = map { substr $_, 0, 1 } @rest;
然后join
他们在一起:
join '', $first, @initials;
全部放在一起:
for (@arrayOfNames) {
my ($first, @rest) = split;
print join '', $first, map { substr $_, 0, 1 } @rest;
}
答案 1 :(得分:4)
我想不出用regex轻松做到这一点的方法,但这有效:
#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;
my @names = ('Fred Smith', 'Dave Davidson', 'John', 'Andy Wood', 'Robin van Persie');
my @abbvr = map { my ($n, @n) = split;
$n .= substr($_, 0, 1) for @n;
$n } @names;
print Dumper @abbvr;
答案 2 :(得分:3)
使用正则表达式:
use strict;
use warnings;
chomp(my @names = <DATA>);
my @abbrs = map {s/\s+(.)\S*/$1/gr} @names;
use Data::Dump;
dd @abbrs;
__DATA__
Fred Smith
Dave Davidson
John
Andy Wood
Robin van Persie
输出:
("FredS", "DaveD", "John", "AndyW", "RobinvP")
请注意,如果使用不支持/r
开关的较旧版本的perl,以下内容将正常运行:
my @abbrs = map {(my $ab = $_) =~ s/\s+(.)\S*/$1/g\; $ab} @names;
另外,另一种可能的边缘情况是John Paul II
。也许这个缩写应该等于JohnPII
?如果是这样,以下调整将处理s/\s+(.[A-Z]*)\S*/$1/gr