8

Удаление акцентов/диакритических знаков в строке на JavaScript

1

Тема: Как удалить акцентированные символы из строки?

Я работаю над проектом, где нужно удалить акцентированные символы из строк. В частности, я сталкиваюсь с проблемами в Internet Explorer 6, где мой текущий код не работает должным образом. Вот что у меня есть:

accentsTidy = function(s){
    var r=s.toLowerCase();
    r = r.replace(new RegExp(/\s/g),"");
    r = r.replace(new RegExp(/[àáâãäå]/g),"a");
    r = r.replace(new RegExp(/æ/g),"ae");
    r = r.replace(new RegExp(/ç/g),"c");
    r = r.replace(new RegExp(/[èéêë]/g),"e");
    r = r.replace(new RegExp(/[ìíîï]/g),"i");
    r = r.replace(new RegExp(/ñ/g),"n");                
    r = r.replace(new RegExp(/[òóôõö]/g),"o");
    r = r.replace(new RegExp(/œ/g),"oe");
    r = r.replace(new RegExp(/[ùúûü]/g),"u");
    r = r.replace(new RegExp(/[ýÿ]/g),"y");
    r = r.replace(new RegExp(/\W/g),"");
    return r;
};

Проблема в том, что кажется, IE6 не любит мои регулярные выражения, и они не работают так, как я ожидал. Как я могу модифицировать этот код или использовать другой подход, чтобы корректно обработать акцентированные символы в IE6? Спасибо!

5 ответ(ов)

0

Этот скрипт на JavaScript быстро удаляет акценты из строк, основываясь на стандарте Unicode. Он использует объект Latinise, в котором хранится карта с заменами символов с акцентами на латинские символы. Вот пример кода:

var Latinise={}; 
Latinise.latin_map={
    "Á":"A","Ă":"A","Ắ":"A","Ặ":"A","Ằ":"A","Ẳ":"A","Ẵ":"A","Ǎ":"A","Â":"A",
    ... // (остальные замены)
    "ž":"z","ẑ":"z","ʑ":"z","Ⱬ":"z","ż":"z","ẓ":"z","ȥ":"z","ẕ":"z"
};
String.prototype.latinise=function() {
    return this.replace(/[^A-Za-z0-9\[\] ]/g, function(a) {
        return Latinise.latin_map[a] || a;
    });
};
String.prototype.latinize=String.prototype.latinise;
String.prototype.isLatin=function() {
    return this == this.latinise();
}

Вот примеры использования этого кода:

> "Piqué".latinise();
"Pique"
> "Piqué".isLatin();
false
> "Pique".isLatin();
true
> "Piqué".latinise().isLatin();
true

Это полезно, если вам нужно нормализовать текст, чтобы избежать проблем с кодировками или акцентами.

Если вы беспокоитесь о целостности карты латинизации при копировании и вставке, вы можете использовать закодированную строку в формате Base64:

var base64map="eyLDgSI6IkEiLCLEgiI6IkEiLCLhuq4iOiJBIiwi...";
var Latinise={};
Latinise.latin_map=JSON.parse(decodeURIComponent(escape(atob(base64map))));

Это гарантирует, что вы не потеряете данные при переносе кода.

0

Формат для создания нового объекта RegExp выглядит следующим образом:

RegExp(что-то, 'модификаторы');

В вашем случае это будет выглядеть так:

accentsTidy = function(s) {
    var r = s.toLowerCase();
    r = r.replace(new RegExp("\\s", 'g'), ""); // Удаляем пробелы
    r = r.replace(new RegExp("[àáâãäå]", 'g'), "a"); // Заменяем разные варианты "a"
    r = r.replace(new RegExp("æ", 'g'), "ae"); // Заменяем "æ" на "ae"
    r = r.replace(new RegExp("ç", 'g'), "c"); // Заменяем "ç" на "c"
    r = r.replace(new RegExp("[èéêë]", 'g'), "e"); // Заменяем "e" с акцентами
    r = r.replace(new RegExp("[ìíîï]", 'g'), "i"); // Заменяем "i" с акцентами
    r = r.replace(new RegExp("ñ", 'g'), "n"); // Заменяем "ñ" на "n"
    r = r.replace(new RegExp("[òóôõö]", 'g'), "o"); // Заменяем "o" с акцентами
    r = r.replace(new RegExp("œ", 'g'), "oe"); // Заменяем "œ" на "oe"
    r = r.replace(new RegExp("[ùúûü]", 'g'), "u"); // Заменяем "u" с акцентами
    r = r.replace(new RegExp("[ýÿ]", 'g'), "y"); // Заменяем "y" с акцентами
    r = r.replace(new RegExp("\\W", 'g'), ""); // Удаляем все не буквенно-цифровые символы
    return r; // Возвращаем очищенную строку
};

Эта функция будет полезна для очистки строки от акцентированных символов и пробелов, а также для удаления специальных символов.

0

Вот перевод на русский в стиле ответа на StackOverflow:


Сокращенный код на основе отличного решения Иэна Эллиотта:

accentsTidy = function(s) {
    var r = s.toLowerCase();
    non_asciis = {'a': '[àáâãäå]', 'ae': 'æ', 'c': 'ç', 'e': '[èéêë]', 'i': '[ìíîï]', 'n': 'ñ', 'o': '[òóôõö]', 'oe': 'œ', 'u': '[ùúûűü]', 'y': '[ýÿ]'};
    for (i in non_asciis) { r = r.replace(new RegExp(non_asciis[i], 'g'), i); }
    return r;
};

Редактирование: Исправлен неработающий код.


Если вам нужны дополнительные разъяснения по этому коду, не стесняйтесь задавать вопросы!

0

Есть много решений этой задачи, но я думаю, что данное очень простое и достаточно хорошее:

function remove_accents(strAccents) {
    var strAccents = strAccents.split('');
    var strAccentsOut = new Array();
    var strAccentsLen = strAccents.length;
    var accents = "ÀÁÂÃÄÅàáâãäåÒÓÔÕÕÖØòóôõöøÈÉÊËèéêëÇçðÐÌÍÎÏìíîïÙÚÛÜùúûüÑñŠšŸÿýŽž";
    var accentsOut = "AAAAAAaaaaaaOOOOOOOooooooEEEEeeeeCcdDIIIIiiiiUUUUuuuuNnSsYyyZz";
    for (var y = 0; y < strAccentsLen; y++) {
        if (accents.indexOf(strAccents[y]) != -1) {
            strAccentsOut[y] = accentsOut.substr(accents.indexOf(strAccents[y]), 1);
        } else
            strAccentsOut[y] = strAccents[y];
    }
    strAccentsOut = strAccentsOut.join('');

    return strAccentsOut;
}

Если вам также нужно удалить специальные символы и преобразовать пробелы и дефисы в нижние подчеркивания, сделайте следующее:

string = remove_accents(string);
string = string.replace(/[^a-z0-9\s]/gi, '').replace(/[-\s]/g, '_');

Этот код сначала удаляет акценты, а затем обрабатывает строку, удаляя все символы, кроме букв и цифр, и заменяя пробелы и дефисы на подчеркивания.

0

Одно из решений, которое, судя по представленному тесту, работает значительно быстрее: http://jsperf.com/diacritics/9

function removeDiacritics(str) {
   return str.replace(/[^A-Za-z0-9\s]+/g, function(a){
      return diacriticsMap[a] || a; 
   });
}
removeDiacritics(teste);

Рабочий пример: http://jsbin.com/sovorute/1/edit

Обоснование: Одной из причин, по которой этот способ гораздо быстрее, является то, что мы проходим только через специальные символы, выбранные с помощью отрицательного регулярного выражения. Самый быстрый тест (Итерация строки без in) выполняет 1001 итерацию текста, то есть проходит через каждый символ. В данном же случае итерация происходит всего 35 раз и при этом возвращает такой же результат. Помните, что это решение заменяет только те символы, которые указаны в карте.

Классическая статья на эту тему: http://alistapart.com/article/accent-folding-for-auto-complete

Кредит: http://semplicewebsites.com/removing-accents-javascript, также предоставляет удобную карту символов.

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь