操纵单个和多个单词字符串

时间:2014-06-20 09:36:17

标签: regex perl foreach

我有一个包含许多名字的数组:

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

如何更改以满足这一个单词和两个以上的单词名称? 是应该将一个单词和两个以上的单词名称移动到一个新的数组中然后再处理,还是可以改变正则表达式来满足这个要求?

3 个答案:

答案 0 :(得分:5)

您可以使用split代替正则表达式将名字与其他名称分开:

my ($first, @rest) = split;

然后在substrmap提取缩写:

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