How to separate Chinese characters one by one?
If there is not a special character (such as space , : , etc.) between the name and the name.
Then how to split the Chinese characters below.
use strict;
use warnings;
use Data::Dumper;
my $fh = \*DATA;
my $fname; # 小三;
my $lname; # 张 ;
while(my $name = <$fh>)
{
$name =~ ??? ;
print $fname"/n";
print $lname;
}
__DATA__
张小三
Exit
小三 张
[Update]
WinXP. ActivePerl5.10.1 is used.
a source to share
You're in trouble because you ignore decoding binary data to Perl strings at input time and encode Perl strings to binary data at output time. The reason for this is that regex and his friend split
work correctly on Perl strings.
(?<=.)
means "after the first character". Thus, this program will not work correctly with 复姓 / compound family names; keep in mind that they are rare but exist. To always correctly separate the first name into the last name and the given parts of the name, you need to use a dictionary with family names.
Linux version:
use strict;
use warnings;
use Encode qw(decode encode);
while (my $full_name = <DATA>) {
$full_name = decode('UTF-8', $full_name);
chomp $full_name;
my ($family_name, $given_name) = split(/(?<=.)/, $full_name, 2);
print encode('UTF-8',
sprintf('The full name is %s, the family name is %s, the given name is %s.', $full_name, $family_name, $given_name)
);
}
__DATA__
张小三
Output:
The full name is 张小三, the family name is 张, the given name is 小三.
Windows version:
use strict;
use warnings;
use Encode qw(decode encode);
use Encode::HanExtra qw();
while (my $full_name = <DATA>) {
$full_name = decode('GB18030', $full_name);
chomp $full_name;
my ($family_name, $given_name) = split(/(?<=.)/, $full_name, 2);
print encode('GB18030',
sprintf('The full name is %s, the family name is %s, the given name is %s.', $full_name, $family_name, $given_name)
);
}
__DATA__
张小三
Output:
The full name is 张小三, the family name is 张, the given name is 小三.
a source to share
You will need a heuristic to separate first and last names. Here's a working code, assuming the last name (last name) is one character (first) and all other characters (at least one) belong to the first name (first name):
EDIT: Changed the program to ignore invalid lines and not die.
use strict;
use utf8;
binmode STDOUT, ":utf8";
while (my $name = <DATA>) {
my ($lname, $fname) = $name =~ /^(\p{Han})(\p{Han}+)$/ or next;
print "First name: $fname\nLast name: $lname\n";
}
__DATA__
张小三
When I run this program from the command line, I get this output:
First name: 小三
Last name: 张
a source to share