Как я могу изменить расширенные символы латинского алфавита на их эквиваленты ASCII без акцента? - PullRequest
6 голосов
/ 16 января 2009

Мне нужно универсальное регулярное выражение транслитерации или подстановки, которое будет отображать расширенные латинские символы в похожие символы ASCII, а все остальные расширенные символы в '' (пустая строка), чтобы ...

  • é становится е

  • ê становится e

  • а становится

  • C становится C

  • Ď становится D

и т. Д., Но такие вещи, как ‡ или Ω или striped, просто раздеваются.

Ответы [ 5 ]

8 голосов
/ 16 января 2009

Используйте Unicode :: Normalize, чтобы получить NFD ($ str). В этой форме все символы с диакритическими знаками будут превращены в базовые символы, за которыми следует комбинирующий диакритический знак. Затем просто удалите все не-ASCII символы.

2 голосов
/ 16 января 2009

Текст :: Unaccent или альтернативно Текст :: Unaccent :: PurePerl звучит так, как вы просите, по крайней мере, в первой его половине.

$unaccented = unac_string($charset, $string);

Удаление всех не-ASCII символов будет относительно простым.

s/[^\000-\177]+//g;
2 голосов
/ 16 января 2009

Может быть, модуль CPAN может помочь?

Text :: Unidecode выглядит многообещающе, хотя и не снимает ‡, Ω или ‰. Скорее они заменяются ++, O и% o. Это может или не может быть то, что вы хотите.

Text :: Unaccent , еще один кандидат, но только в части избавления от акцентов.

1 голос
/ 17 января 2009

Все блестящие ответы. Но на самом деле никто не работал. Размещение расширенных символов непосредственно в исходном коде вызывало проблемы при работе в окнах терминала или различных редакторах кода / текста на разных платформах. Мне удалось опробовать Unicode :: Normalize, Text :: Unidecode и Text :: Unaccent, но я не смог заставить никого из них делать именно то, что я хочу.

В конце я просто перечислил все символы, которые хотел транслитерировать сам для UTF-8 (это наиболее часто встречающаяся кодовая страница в моих входных данных).

Мне понадобились две дополнительные замены, чтобы позаботиться о æ и Æ, которые я хочу сопоставить двум символам

Для заинтересованных сторон окончательный код: (tr - одна строка)

$word =~ tr/\xC0\xC1\xC2\xC3\xC4\xC5\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF
\xD0\xD1\xD2\xD3\xD4\xD5\xD6\xD8\xD9\xDA\xDB\xDC\xDD\xE0\xE1\xE2\xE3\xE4
\xE5\xE7\xE8\xE9\xEA\xEB\xEC\xED\xEE\xEF\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF8
\xF9\xFA\xFB\xFC\xFD\xFF/AAAAAACEEEEIIIIDNOOOOOOUUUUYaaaaaaceeeeiiiionoo
oooouuuuyy/;
$word =~ s/\xC6/AE/g;
$word =~ s/\xE6/ae/g;
$word =~ s/[^\x00-\x7F]+//g;

Поскольку такие вещи, как Ď, не являются частью UTF-8, они не так часто встречаются в моих входных данных. Для входа не в формате UTF-8, я решил потерять все, что выше 127.

0 голосов
/ 16 января 2009

Когда я хочу перевести некоторую строку, а не только символы, я использую такой подход:

my %trans = (
  'é' => 'e',
  'ê' => 'e',
  'á' => 'a',
  'ç' => 'c',
  'Ď' => 'D',
  map +($_=>''), qw(‡ Ω ‰)
};

my $re = qr/${ \(join'|', map quotemeta, keys %trans)}/;

s/($re)/$trans{$1}/ge;

Если вам нужны более сложные, вы можете использовать функции вместо строковых констант. При таком подходе вы можете делать все, что захотите. Но для вашего случая tr должно быть более эффективным:

tr/éêáçĎ/eeacD/;
tr/‡Ω‰//d;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...