Удаление акцентов/диакритических знаков в строке на JavaScript
Тема: Как удалить акцентированные символы из строки?
Я работаю над проектом, где нужно удалить акцентированные символы из строк. В частности, я сталкиваюсь с проблемами в 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 ответ(ов)
Этот скрипт на 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))));
Это гарантирует, что вы не потеряете данные при переносе кода.
Формат для создания нового объекта 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; // Возвращаем очищенную строку
};
Эта функция будет полезна для очистки строки от акцентированных символов и пробелов, а также для удаления специальных символов.
Вот перевод на русский в стиле ответа на 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;
};
Редактирование: Исправлен неработающий код.
Если вам нужны дополнительные разъяснения по этому коду, не стесняйтесь задавать вопросы!
Есть много решений этой задачи, но я думаю, что данное очень простое и достаточно хорошее:
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, '_');
Этот код сначала удаляет акценты, а затем обрабатывает строку, удаляя все символы, кроме букв и цифр, и заменяя пробелы и дефисы на подчеркивания.
Одно из решений, которое, судя по представленному тесту, работает значительно быстрее: 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, также предоставляет удобную карту символов.
Где найти документацию по форматированию даты в JavaScript?
В чем разница между String.slice и String.substring?
Проверка соответствия строки регулярному выражению в JS
Существует ли ссылка на "последнюю" библиотеку jQuery в Google APIs?
Как создать диалог с кнопками "Ок" и "Отмена"