File Coverage

lib/Lingua/EN/NameParse/Simple.pm
Criterion Covered Total %
statement 10 12 83.3
branch n/a
condition n/a
subroutine 4 4 100.0
pod n/a
total 14 16 87.5


line stmt bran cond sub pod time code
1             package Lingua::EN::NameParse::Simple;
2              
3 2     2   58810 use warnings;
  2         5  
  2         71  
4 2     2   12 use strict;
  2         6  
  2         55  
5 2     2   4880 use DBI;
  2         42778  
  2         163  
6 2     2   2608 use DB_File;
  0            
  0            
7             use Fcntl ':flock';
8             use locale;
9              
10             =head1 NAME
11              
12             Lingua::EN::NameParse::Simple - Parse an English name into component parts
13              
14             =head1 VERSION
15              
16             Version 0.14
17              
18             =cut
19              
20             our $VERSION = '0.14';
21              
22             =head1 SYNOPSIS
23              
24             Invoke this package as follows:
25              
26             use Lingua::EN::NameParse::Simple;
27             my %name = Lingua::EN::NameParse::Simple::ParseName($fullname);
28            
29             # %name will contain available values for these keys:
30             # TITLE, FIRST, MIDDLE, LAST, SUFFIX
31              
32             # unless the FIRST and LAST keys are populated
33             # or if digits are found in a key other than SUFFIX,
34             # an ERROR key is returned instead.
35              
36             unless( defined( $name{'ERROR'} )){
37             print Dumper( \%name );
38             }
39              
40             =head1 FUNCTIONS
41              
42             =head2 ParseName
43              
44             my %name = Lingua::EN::NameParse::Simple::ParseName($fullname);
45              
46             returns values for these keys:
47             TITLE, FIRST, MIDDLE, LAST, SUFFIX
48              
49             =cut
50              
51             sub ParseName {
52             my(@returnarray,$namearraysize,$i,$j);
53             my(@namearray,$fullname,@validtitle,@validsuffix);
54             my($titlematch,%name);
55             my($nameelement,$tmp,$lnamematch,$mnamematch);
56             my($fnamematch,,$suffixmatch,$tmpelement);
57             $fullname=$_[0];
58             @namearray=split(/\s+/,$fullname);
59             @validtitle = ('MR', 'MS', 'MRS', 'MISS', 'MISTER', 'DR', 'DOCTOR', 'REV', 'REVEREND', 'PASTOR', 'HONORABLE');
60             @validsuffix = ('SR', 'SENIOR', 'JR', 'JUNIOR', 'II', 'III', 'IV');
61             $namearraysize=@namearray; # Number of items in array
62             $i=0; # Keep track of name element
63             $titlematch=0;
64             $lnamematch=0;
65             $mnamematch=0;
66             $fnamematch=0;
67             $suffixmatch=0;
68             NAMEPARSE:foreach(@namearray) {
69             $nameelement=$_;
70             if(($i+1) == $namearraysize) {
71             # Test to see if last element
72             # Either Suffix or Last Name
73             foreach(@validsuffix) {
74             $tmp=uc($nameelement);
75             $tmp=~s/\[,.]//g;
76             $tmp=~s/\,//g;
77             $tmp=~s/\.//g;
78             if($tmp eq $_) {
79             # Suffix detected
80             $returnarray[$i][0]="SUFFIX";
81             $nameelement=~s/\[,.]//g;
82             $returnarray[$i][1]=$nameelement;
83             $suffixmatch++;
84             if($lnamematch == 0 && $returnarray[$i-1][0] eq "MIDDLE") {
85             # If no last name has been found then next to last element
86             # that is a middle name becomes the last name
87             $returnarray[$i-1][0] = "LAST";
88             }
89             $i++;
90             next NAMEPARSE;
91             }
92             }
93             if($lnamematch == 0) {
94             # Since Suffix is not found and lastname not found
95             # must be a last name
96             $returnarray[$i][0]="LAST";
97             $nameelement=~s/\.//g;
98             $nameelement=~s/\,//g;
99             $returnarray[$i][1]=$nameelement;
100             $lnamematch++;
101             $i++;
102             next NAMEPARSE;
103             } else {
104             # Must be a middle name
105             $returnarray[$i][0]="MIDDLE";
106             $nameelement=~s/\[,.]//g;
107             $returnarray[$i][1]=$nameelement;
108             $mnamematch=1;
109             $i++;
110             next NAMEPARSE;
111             }
112             } elsif(($i+2) == $namearraysize) {
113             # Test to see if second to last element
114             # See if element is part of the first 3
115             if($i < 3) {
116             # Part of first 3 crucial elements
117             if($i == 0) {
118             # Two element array, first element
119             # Check to see if title
120             VALIDTITLE:foreach(@validtitle) {
121             # See if there is a title match
122             $tmp=uc($nameelement);
123             $tmp=~s/\[.,]//g;
124             $tmp=~s/\,//g;
125             $tmp=~s/\.//g;
126             # print "$tmp vs $_ test var\n";
127             if($tmp eq $_) {
128             # Match!
129             $returnarray[$i][0]="TITLE";
130             $returnarray[$i][1]=$nameelement;
131             $titlematch++;
132             $i++;
133             next NAMEPARSE;
134             }
135             }
136             if(substr($nameelement,length($nameelement)-1,1) eq ",") {
137             # Check to see if last name
138             $returnarray[$i][0]="LAST";
139             $returnarray[$i][1]=$nameelement;
140             $lnamematch++;
141             $i++;
142             next NAMEPARSE;
143             } else {
144             # Otherwise, must be a first name
145             $returnarray[$i][0]="FIRST";
146             $returnarray[$i][1]=$nameelement;
147             $fnamematch++;
148             $i++;
149             next NAMEPARSE;
150             }
151             } elsif($i == 1) {
152             # Three element array, second element
153             if($returnarray[$i-1][0] eq "TITLE" || $returnarray[$i-1][0] eq "LAST") {
154             # Must be a first name
155             $returnarray[$i][0]="FIRST";
156             $nameelement=~s/\,//g;
157             $nameelement=~s/\.//g;
158             $returnarray[$i][1]=$nameelement;
159             $fnamematch=1;
160             $i++;
161             next NAMEPARSE;
162             } elsif($returnarray[$i-1][0] eq "FIRST") {
163             # Must be a middle name
164             $returnarray[$i][0]="MIDDLE";
165             $nameelement=~s/\,//g;
166             $nameelement=~s/\.//g;
167             $returnarray[$i][1]=$nameelement;
168             $mnamematch=1;
169             $i++;
170             next NAMEPARSE;
171             }
172             } elsif($i == 2) {
173             # Four element array, third element
174             # Must be a middle or a last name but must set to middle until last element is detected
175             $returnarray[$i][0]="MIDDLE";
176             $nameelement=~s/\,//g;
177             $nameelement=~s/\.//g;
178             $returnarray[$i][1]=$nameelement;
179             $mnamematch=1;
180             $i++;
181             next NAMEPARSE;
182             }
183             } else {
184             # Must be a middle (or last name but won't know that
185             # until we check the last element so set to middle name)
186             $returnarray[$i][0]="MIDDLE";
187             $nameelement=~s/\,//g;
188             $nameelement=~s/\.//g;
189             $returnarray[$i][1]=$nameelement;
190             $mnamematch=1;
191             $i++;
192             next NAMEPARSE;
193             }
194             } elsif($i > 2 && ($i+2) < $namearraysize) {
195             # All elements after the 3rd and before 2nd to last
196             $returnarray[$i][0]="MIDDLE";
197             $nameelement=~s/\,//g;
198             $nameelement=~s/\.//g;
199             $returnarray[$i][1]=$nameelement;
200             $mnamematch=1;
201             $i++;
202             next NAMEPARSE;
203             } elsif($i == 0) {
204             # Test to see if first element
205             # Test to see if this is a title
206             VALIDTITLE:foreach(@validtitle) {
207             # See if there is a title match
208             $tmp=uc($nameelement);
209             $tmp=~s/\[.,]//g;
210             $tmp=~s/\,//g;
211             $tmp=~s/\.//g;
212             # print "$tmp vs $_ test var\n";
213             if($tmp eq $_) {
214             # Match!
215             $returnarray[$i][0]="TITLE";
216             $returnarray[$i][1]=$nameelement;
217             $titlematch++;
218             $i++;
219             next NAMEPARSE;
220             }
221             }
222             if(substr($nameelement,length($nameelement)-1,1) eq ",") {
223             # Detected a last name
224             $returnarray[$i][0]="LAST";
225             $nameelement=~s/\,//g;
226             $nameelement=~s/\.//g;
227             $returnarray[$i][1]=$nameelement;
228             $i++;
229             $lnamematch++;
230             next NAMEPARSE;
231             } else {
232             # If all else fails, must be first name
233             $returnarray[$i][0]="FIRST";
234             $nameelement=~s/\,//g;
235             $nameelement=~s/\.//g;
236             $returnarray[$i][1]=$nameelement;
237             $i++;
238             $fnamematch++;
239             next NAMEPARSE;
240             }
241             } elsif($i == 1) {
242             # Test to see if second element
243             if($returnarray[$i-1][0] eq "TITLE" || $returnarray[$i-1][0] eq "LAST") {
244             # First Name
245             $returnarray[$i][0]="FIRST";
246             $nameelement=~s/\,//g;
247             $nameelement=~s/\.//g;
248             $returnarray[$i][1]=$nameelement;
249             $i++;
250             $fnamematch++;
251             next NAMEPARSE;
252             } else {
253             # Middle Name
254             $returnarray[$i][0]="MIDDLE";
255             $nameelement=~s/\,//g;
256             $nameelement=~s/\.//g;
257             $returnarray[$i][1]=$nameelement;
258             $i++;
259             $mnamematch++;
260             next NAMEPARSE;
261             }
262             } elsif($i == 2) {
263             # Test to see if third element
264             # Must be middle if there since there are more than one elements after this
265             # Middle Name
266             $returnarray[$i][0]="MIDDLE";
267             $nameelement=~s/\,//g;
268             $nameelement=~s/\.//g;
269             $returnarray[$i][1]=$nameelement;
270             $i++;
271             $mnamematch++;
272             next NAMEPARSE;
273             }
274             }
275             foreach $j (0...(scalar(@returnarray)-1)) {
276             $name{$returnarray[$j][0]} = $returnarray[$j][1];
277             }
278             foreach my $key ('TITLE','FIRST','MIDDLE','LAST'){
279             if( defined( $name{$key} ) && $name{$key} =~ m/[0-9]/){
280             $name{'ERROR'} = 'We do not expect to see digits in a person\'s name';
281             }
282             }
283             unless( defined($name{'LAST'}) && defined($name{'FIRST'}) ){
284             $name{'ERROR'} = 'Does not appear to be a person\'s name conforming to traditional English format';
285             }
286             if( defined( $name{'ERROR'} )){
287             foreach my $key ('TITLE','FIRST','MIDDLE','LAST','SUFFIX'){ delete $name{$key}; }
288             }
289             return (%name);
290             } # End ParseName
291              
292             =head1 AUTHOR
293              
294             Hugh Esco, C<< >> and James Jones
295              
296             =head1 BUGS
297              
298             Please report any bugs or feature requests
299             to C
300             rt.cpan.org>, or through the web interface at
301             L.
302             I will be notified, and then you'll automatically be notified
303             of progress on your bug as I make changes.
304              
305             =head1 SUPPORT
306              
307             You can find documentation for this module with the perldoc command.
308              
309             perldoc Lingua::EN::NameParse::Simple
310              
311              
312             You can also look for information at:
313              
314             =over 4
315              
316             =item * RT: CPAN's request tracker
317              
318             L
319              
320             =item * AnnoCPAN: Annotated CPAN documentation
321              
322             L
323              
324             =item * CPAN Ratings
325              
326             L
327              
328             =item * Search CPAN
329              
330             L
331              
332             =back
333              
334              
335             =head1 ACKNOWLEDGEMENTS
336              
337              
338             =head1 COPYRIGHT & LICENSE
339              
340             Copyright (C) 2004-2012 by Hugh Esco, James Jones and the Georgia Green Party
341              
342             originally written as:
343              
344             parser.pm -- Parses a name into its constituent parts
345             Copyright (C) 2004 by Hugh Esco, James Jones and the Georgia Green Party
346              
347             Original concept and early buggy version by Esco, original
348             working module refactored by James Jones as parser.pm in 2004.
349             In 2006 the state Committee of the Georgia Green Party agreed
350             to release generally useful portions of its code base under
351             the Gnu Public License. The test suite was added and the
352             module renamed and packaged for CPAN distribution by Esco
353             doing business as CampaignFoundations.com in 2010. In early
354             2012 Esco again extended this module to report an ERROR key
355             in certain circumstances.
356              
357             This program is free software; you can redistribute it and/or
358             modify it under the terms of the GNU General Public License
359             as published by the Free Software Foundation; version 2 dated
360             June, 1991 or at your option any later version.
361              
362             This program is distributed in the hope that it will be useful,
363             but WITHOUT ANY WARRANTY; without even the implied warranty of
364             MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
365             GNU General Public License for more details.
366              
367             A copy of the GNU General Public License is available in the
368             source tree; if not, write to the Free Software Foundation,
369             Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
370              
371             =cut
372              
373             1; # End of Lingua::EN::NameParse::Simple
374