在Perl中,如何用简单的ASCII字符替换UTF8字符,例如\x91、\x{2018}、\x{2013}、\x{2014}?

在Perl中,如何用简单的ASCII字符替换UTF8字符,例如\x91、\x{2018}、\x{2013}、\x{2014}?,perl,encoding,character-encoding,ascii,non-ascii-characters,Perl,Encoding,Character Encoding,Ascii,Non Ascii Characters,我正在处理各种文章,我遇到的问题是,不同的作者使用不同的字符作为标点符号 例如,我目前使用的几个文档具有以下字符: \x91 \x92 \x{2018} \x{2019} 所有这些字符都代表一个简单的引号 我想做的是简化文章,使它们具有相同的格式样式 有人知道将这些字符和类似字符(如双引号、破折号等)转换为简单ASCII字符的模块或方法吗 我目前正在做以下工作: sub fix_chars_in_document { my $document = shift; $documen

我正在处理各种文章,我遇到的问题是,不同的作者使用不同的字符作为标点符号

例如,我目前使用的几个文档具有以下字符:

\x91
\x92
\x{2018}
\x{2019}
所有这些字符都代表一个简单的引号

我想做的是简化文章,使它们具有相同的格式样式

有人知道将这些字符和类似字符(如双引号、破折号等)转换为简单ASCII字符的模块或方法吗

我目前正在做以下工作:

sub fix_chars_in_document {
    my $document = shift;
    $document =~ s/\xa0/ /g;
    $document =~ s/\x91/'/g;
    $document =~ s/\x92/'/g;
    $document =~ s/\x93/"/g;
    $document =~ s/\x94/"/g;
    $document =~ s/\x97/-/g;
    $document =~ s/\xab/"/g;
    $document =~ s/\xa9//g;
    $document =~ s/\xae//g;
    $document =~ s/\x{2018}/'/g;
    $document =~ s/\x{2019}/'/g;
    $document =~ s/\x{201C}/"/g;
    $document =~ s/\x{201D}/"/g;
    $document =~ s/\x{2022}//g;
    $document =~ s/\x{2013}/-/g;
    $document =~ s/\x{2014}/-/g;
    $document =~ s/\x{2122}//g; 
    return $document ;
}

但这非常困难,因为我必须手动查找字符并替换它们。

首先,您的解决方案将受益于哈希

my %asciify = (
   chr(0x00A0) => ' ',
   chr(0x0091) => "'",
   chr(0x0092) => "'",
   chr(0x0093) => '"',
   chr(0x0094) => '"',
   chr(0x0097) => '-',
   chr(0x00AB) => '"',
   chr(0x00A9) => '/',
   chr(0x00AE) => '/',
   chr(0x2018) => "'",
   chr(0x2019) => "'",
   chr(0x201C) => '"',
   chr(0x201D) => '"',
   chr(0x2022) => '/',
   chr(0x2013) => '-',
   chr(0x2014) => '-',
   chr(0x2122) => '/',
);

my $pat = join '', map quotemeta, keys %asciify;
my $re = qr/[$pat]/;

sub fix_chars {
    my ($s) = @_;
    $s =~ s/($re)/$asciifi{$1}/g;
    return $s;
}
也就是说,你想要

仅标点符号:

use Text::Unidecode qw( unidecode );
s/(\p{Punct}+)/ unidecode($1) /eg;

首先,您的解决方案将受益于散列

my %asciify = (
   chr(0x00A0) => ' ',
   chr(0x0091) => "'",
   chr(0x0092) => "'",
   chr(0x0093) => '"',
   chr(0x0094) => '"',
   chr(0x0097) => '-',
   chr(0x00AB) => '"',
   chr(0x00A9) => '/',
   chr(0x00AE) => '/',
   chr(0x2018) => "'",
   chr(0x2019) => "'",
   chr(0x201C) => '"',
   chr(0x201D) => '"',
   chr(0x2022) => '/',
   chr(0x2013) => '-',
   chr(0x2014) => '-',
   chr(0x2122) => '/',
);

my $pat = join '', map quotemeta, keys %asciify;
my $re = qr/[$pat]/;

sub fix_chars {
    my ($s) = @_;
    $s =~ s/($re)/$asciifi{$1}/g;
    return $s;
}
也就是说,你想要

仅标点符号:

use Text::Unidecode qw( unidecode );
s/(\p{Punct}+)/ unidecode($1) /eg;

当然,这是假设您实际上仅限于ASCII。我希望你不要只是采取用洗澡水把孩子扔掉的方法来解决问题。谢谢你的建议。我尝试了Text::Unidecode,但它也会将像“a”这样的字符(上面有东西)转换为简单的a等。我只需要将破折号、引号和其他简单的标点符号转换为ascii。当然,这是假设您确实只限于ascii。我希望你不要只是采取用洗澡水把孩子扔掉的方法来解决问题。谢谢你的建议。我试过Text::Unidecode,但它也会将像“a”这样的字符(上面有东西)转换为简单的a等。我只需要将破折号、引号和其他简单的标点字符转换为ascii。也许可以看看CPAN上的Text::Unidecode。@DaveCross我试过了,但它会影响所有字符,而不仅仅是破折号、点,引号。也许看看CPAN上的Text::Unidecode。@DaveCross我刚试过,但它会影响所有字符,而不仅仅是破折号、点和引号。