【问题标题】:Normalizing ASCII characters规范化 ASCII 字符
【发布时间】:2012-05-31 07:42:13
【问题描述】:

我需要对诸如“quee”之类的字符串进行规范化,但我似乎无法将扩展的 ASCII 字符(例如 é、á、í 等)转换为罗马/英语版本。我尝试了几种不同的方法,但到目前为止没有任何效果。关于这个一般主题有相当多的材料,但我似乎找不到这个问题的有效答案。

这是我的代码:

#transliteration solution (works great with standard chars but doesn't find the 
#special ones) - I've tried looking for both \x{130} and é with the same result.
$mystring =~ tr/\\x{130}/e/;

#converting into array, then iterating through and replacing the specific char
#( same result as the above solution )
my @breakdown = split( "",$mystring );

foreach ( @breakdown ) {
    if ( $_ eq "\x{130}" ) {
        $_ = "e";
        print "\nArray Output: @breakdown\n";
    }
    $lowercase = join( "",@breakdown );
}

【问题讨论】:

    标签: perl ascii normalization


    【解决方案1】:

    对于关于摆脱任何剩余符号但保留字母和数字的第二个问题,将您的最后一个正则表达式从 s/\W+//g 更改为 s/[^a-zA-Z0-9 ]+//g。由于您已经对输入的其余部分进行了规范化,因此使用该正则表达式将删除任何不是 a-z、A-Z、0-9 或空格的内容。在开头使用 [] 和 ^ 表示您要查找不在括号其余部分中的所有内容。

    【讨论】:

      【解决方案2】:

      在工作和重新工作之后,这就是我现在所拥有的。它可以做我想做的一切,除了我想在输入字符串中间保留空格以区分单词。

      open FILE, "funnywords.txt";
      
      # Iterate through funnywords.txt
      while ( <FILE> ) {
          chomp;
      
          # Show initial text from file
          print "In: '$_' -> ";
      
          my $inputString = $_;
      
          # $inputString is scoped within a for each loop which dissects
          # unicode characters ( example: "é" splits into "e" and "´" )
          # and throws away accent marks. Also replaces all
          # non-alphanumeric characters with spaces and removes
          # extraneous periods and spaces.
          for ( $inputString ) {
              $inputString = NFD( $inputString ); # decompose/dissect
              s/^\s//; s/\s$//;                   # strip begin/end spaces
              s/\pM//g;                           # strip odd pieces
              s/\W+//g;                           # strip non-word chars
          }
      
          # Convert to lowercase 
          my $outputString = "\L$inputString";
      
          # Output final result
          print "$outputString\n";
      }
      

      不完全确定为什么它会将一些正则表达式和 cmets 染成红色...

      以下是“funnywords.txt”中的几行示例:

      排队

      22.

      ?éÉíóñúÑ¿¡

      [.这个? ]

      aquí, allí

      【讨论】:

        【解决方案3】:

        您的原始代码不起作用的原因是\x{130} 不是é。这是LATIN CAPITAL LETTER I WITH DOT ABOVE (U+0130 or İ)。您的意思是\x{E9} 或只是\xE9(大括号对于两位数是可选的),LATIN SMALL LETTER E WITH ACUTE (U+00E9)

        另外,您的tr 中有一个额外的反斜杠;它应该看起来像 tr/\xE9/e/

        通过这些更改,您的代码将可以工作,尽管我仍然建议使用 CPAN 上的模块之一来处理此类事情。我自己更喜欢Text::Unidecode,因为它处理的不仅仅是重音字符。

        【讨论】:

        • 感谢您的帮助!我实施了您的更改,现在可以使用。事实上,我在交付版本中使用了一个模块,因为它似乎是最优雅的方式,但很高兴知道我离得不远。
        【解决方案4】:

        1) 这个article 应该提供一个相当好的(如果复杂的话)方法。

        它提供了将所有带重音的Unicode字符转换为基本字符+重音的解决方案;完成后,您可以简单地单独删除重音字符。


        2) 另一个选项是 CPAN:Text::Unaccent::PurePerlText::Unaccent 的改进纯 Perl 版本)


        3) 另外,this SO answer 提议Text::Unidecode

        $ perl -Mutf8 -MText::Unidecode -E 'say unidecode("été")'
          ete
        

        【讨论】:

          猜你喜欢
          • 2010-11-25
          • 2010-10-10
          • 2018-09-29
          • 2020-02-12
          • 2011-05-08
          • 2012-04-25
          • 2013-06-29
          • 2021-10-18
          • 1970-01-01
          相关资源
          最近更新 更多