Как найти регистр в тексте

Чтобы составить формулу введём обозначения для результатов

  • «——« символ без регистра
  • «СТРОЧН» строчная (маленькая) буква
  • «ПРОПИСН» прописная (большая) буква

будем определять регистр первого символа текстовой ячейки A1

Для перевода символа в нижний регистр используем функцию СТРОЧН

Для перевода символа в верхний регистр используем функцию ПРОПИСН

для сравнения придётся использовать функцию НАЙТИ

Составим формулу проверки первого символа ячейки A1

=ПСТР(A1;1;1)

условие

=НАЙТИ( СТРОЧН( ПСТР(A1; 1;1)); ПРОПИСН( ПСТР(A1; 1; 1)));0)<>0

определяет есть ли регистр у взятого символа, если регистра нет, условие вернёт ИСТИНА, а если у символа есть регистр, то ЛОЖЬ

если условие выполняется то результат формулы 0 — символ не имеет регистра

если регистр есть то проверяем символ на соответствие прописному символу (результат 2) а в оставшихся случаях результат 1

на языке формул Excel формула для определения регистра выглядит так:

=ЕСЛИ( ЕСЛИОШИБКА( НАЙТИ( СТРОЧН( ПСТР(A1; 1;1)); ПРОПИСН( ПСТР(A1; 1; 1)));0)<>0; «——«; ЕСЛИ( ЕСЛИОШИБКА( НАЙТИ( ПСТР(A1;1;1); ПРОПИСН( ПСТР(A1; 1;1))); 0)<>0; «ПРОПИСН»;»СТРОЧН»))

Проверяем работоспособность:

  • Найти заглавные (прописные) символы латиницы
  • Найти заглавные (прописные) символы кириллицы
  • Найти прописные символы кириллицы или латиницы
  • Найти любые заглавные буквы
  • Найти любые строчные буквы
  • Инструмент “Обнаружить заглавные буквы” в !SEMTools

Поиск именованных сущностей — задача, встречающаяся во множестве профессий. Возникает там, где в текстовом массиве встречаются те или иные имена собственные. Это могут быть названия брендов, ФИО людей, географические названия (топонимы), названия организаций и другие наименования живых и неживых существ.

Все их объединяет простое правило: они пишутся с заглавной буквы, что одновременно становится и своеобразным маркером, позволяющим выделить эти единицы среди остального текста.

При работе с большими массивами данных часто бывает предпочтительнее сначала обнаружить среди ячеек те, что содержат наименования, и далее уже производить более “тяжёлые” операции:

  • массовую замену символов/слов;
  • извлечение текста с заглавными буквами — будь то слова или все содержимое ячейки;
  • удаление символов, слов, словосочетаний или всего содержимого ячеек.

Найти заглавные (прописные) символы латиницы

В Excel есть функция НАЙТИ — она регистрозависимая, что позволяет найти буквы в том регистре, в котором они перечислены. В сочетании с формулой массива эта функция возвращает позицию любого найденного символа из массива.

Поскольку в ASCII-таблице символов прописные английские буквы идут друг за другом по порядку с 65 по 90, можно использовать менее громоздкую формулу массива для их поиска:

{=СЧЁТ(НАЙТИ(СИМВОЛ(СТРОКА(65:90));A1))>0}

Данная формула вернет ИСТИНА, если в ячейке A1 есть хотя бы одна заглавная английская буква.

Важно: фигурные скобки в данном случае появляются сами, вводить их не нужно — нужно вводить формулу без них и использовать сочетание Ctrl + Shift + Enter.

Найти заглавные (прописные) символы кириллицы

Формула аналогична предыдущей, разница лишь в диапазоне символов — от 192 до 223:

{=СЧЁТ(НАЙТИ(СИМВОЛ(СТРОКА(192:223));A1))>0}

Есть пара замечаний к этой формуле:

  • Данный диапазон не включает в себя букву Ё;
  • Язык системы (Windows) должен быть русский, т.к. ASCII-таблица привязана именно к нему.

Найти прописные символы кириллицы или латиницы

Функция не отличается изящностью, но это лучшее, что предоставляет нам Excel в его базовой конфигурации. В зависимости от наличия в строке прописных букв функция возвращает ИСТИНА или ЛОЖЬ.

=СЧЁТ(НАЙТИ({"A":"B":"C":"D":"E":"F":"G":"H":"I":"J":"K":"L":"M":"N":"O":"P":"Q":"R":"S":"T":"U":"V":"W":"X":"Y":"Z":"А":"Б":"В":"Г":"Д":"Е":"Ё":"Ж":"З":"И":"Й":"К":"Л":"М":"Н":"О":"П":"Р":"С":"Т":"У":"Ф":"Х":"Ц":"Ч":"Ш":"Щ":"Ы":"Э":"Ю":"Я"};A1))>0

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

{=СЧЁТ(НАЙТИ(СИМВОЛ(СТРОКА($192:$223));A1))+СЧЁТ(НАЙТИ(СИМВОЛ(СТРОКА($65:$90));A1))>0}

Найти любые заглавные буквы

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

Для поиска заглавных букв нам поможет логика, а именно использование функций СТРОЧН и СОВПАД, последняя из которых позволяет сравнивать значения по регистру.

Логика такова:

  1. Переведём значение в нижний регистр,
  2. Сравним результат с исходным,
  3. Если не совпадут, значит, хотя бы один символ был в верхнем регистре.

А вот и формула:

=НЕ(СОВПАД(СТРОЧН(A1);A1))

Найти любые строчные буквы

Формула аналогична той, что ищет символы в верхнем регистре. Единственное отличие — в ней используется функция ПРОПИСН. Вот формула:

=НЕ(СОВПАД(ПРОПИСН(A1);A1))

Чтобы не приходилось запоминать сложный синтаксис составных функций, можно пользоваться готовыми решениями. !SEMTools располагает набором подобных возможностей, включая и процедуру обнаружения заглавных букв.

Макрос находится в группе “Обнаружить” в первом меню “Символы”. Инструкция безумно проста:

  1. Скопируйте исходный столбец с данными в соседний,
  2. Оставив выделенным скопированный диапазон (иначе говоря, ничего больше не делая), выберите процедуру в меню “Обнаружить символы” —> “Заглавные”.

Как найти заглавные буквы в Excel

Как найти ячейки с большими буквами в Excel с помощью !SEMTools

Ячейки, содержащие заглавные буквы, заменятся на значение “ИСТИНА”, не содержащие их — на “ЛОЖЬ”. Далее можно фильтровать, сортировать, копировать и производить любые дальнейшие действия с маркированными таким образом данными.

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

Смотрите также похожие разделы:

  • Найти кириллицу и латиницу в Excel;
  • Регулярные выражения в Excel – найти, заменить, извлечь;
  • Изменить регистр букв в Excel.

Нужно найти заглавные или строчные буквы в Excel?
В !SEMTools есть это и сотни других готовых решений!

Регистр выделенного текста в документе можно изменить, нажав кнопку Изменить регистр на вкладке Главная.

Изменение регистра

Чтобы изменить регистр выделенного текста в документе:

  1. Выделите текст, регистр которого нужно изменить.

  2. Перейдите на главная > изменить замещающий текст .

  3. Выполните одно из указанных ниже действий.

    • Чтобы сделать первую букву приложения прописной, а остальные оставить строчными, выберите пункт Как в предложениях.

    • Чтобы сделать все буквы строчными, выберите пункт все строчные.

    • Чтобы сделать все буквы прописными, выберите пункт ВСЕ ПРОПИСНЫЕ.

    • Чтобы сделать первую букву в каждом слове прописной, а остальные – строчными, выберите пункт Начинать С Прописных.

    • Чтобы изменить регистр на противоположный (например, переключиться из режима Начинать С Прописных в режим нАЧИНАТЬ сО сТРОЧНЫХ), выберите пункт иЗМЕНИТЬ РЕГИСТР.

    Советы: 

    • Чтобы применить к тексту написание с малых прописных букв, выделите текст, а затем на вкладке Главная в группе Шрифт щелкните стрелку в правом нижнем углу. В диалоговом окне Шрифт в разделе Видоизменение установите флажок малые прописные.

    • Чтобы отменить изменение дела, нажмите CTRL+Z.

    • Чтобы использовать сочетания клавиш для изменения регистра, верхнего и верхнего регистра в каждом слове, выберем текст и нажимаем клавиши SHIFT+F3, пока не будет применен нужный регистр.

См. также

Вставка буквицы

Настройка автозамены: написание прописными буквами

Изменение регистра

Чтобы изменить регистр выделенного текста в документе:

  1. Выделите текст, регистр которого нужно изменить.

  2. Перейдите на главная > изменить замещающий текст .

  3. Выполните одно из указанных ниже действий.

    • Чтобы сделать первую букву приложения прописной, а остальные оставить строчными, выберите пункт Как в предложениях.

    • Чтобы сделать все буквы строчными, выберите пункт все строчные.

    • Чтобы сделать все буквы прописными, выберите пункт ВСЕ ПРОПИСНЫЕ.

    • Чтобы сделать первую букву в каждом слове прописной, а остальные – строчными, выберите пункт Начинать С Прописных.

    • Чтобы изменить регистр на противоположный (например, переключиться из режима Начинать С Прописных в режим нАЧИНАТЬ сО сТРОЧНЫХ), выберите пункт иЗМЕНИТЬ РЕГИСТР.

    Советы: 

    • Чтобы применить к тексту малые буквы, вы выберите текст, а затем в меню Формат выберите Шрифт ,а затем в диалоговом окне Шрифт в области Эффекты выберите поле Малые буквы.

      Small Caps shortcut key: ⌘ +SHIFT+K

    • Чтобы отменить изменение дела, нажмите ⌘ +Z.

    • Чтобы использовать сочетания клавиш для изменения регистра, верхнего регистра и регистра каждого слова, выберем текст и нажимаем клавиши FN+SHIFT+F3, пока не будет применен нужный стиль.

См. также

Вставка буквицы

Настройка автозамены: написание прописными буквами

Веб-приложение PowerPoint поддерживает изменение досье. См. процедуру ниже.

Word в Интернете не поддерживает изменение дела. Откройте документ в настольном приложении и измените его досье. Кроме того, вы можете вручную изменить casing текста в Word в Интернете.

  1. Select the text you want to change.

  2. Перейдите на главная > Дополнительные параметры шрифта > Изменение досье.

    Нажать кнопку "Дополнительные параметры шрифта" (с многолипким нажатием), выбрать изменить шрифт и выбрать нужный вариант.

  3. Выберите нужный регистр.

На днях столкнулся с такой же задачей. Предлагаю свою идею. В ходе написание скрипта были учтены непереводимые в регистр символы, цифры, пробел. При определении ввода верхнего регистра проверяю последний введенный символ.

Ну в общем чего ходить вокруг да около вот функция которая принимает объект и уже на типу объекта берет значение для проверки.

/** 
* return boolean
* true - using Caps Lock
* false - not using Caps Lock
**/
function checkingUp(_obj){

    var symbol = '';
    var type = _obj[0].tagName;

    switch(type)
    {
        case "INPUT" :
            symbol = String(_obj.val());
                break;
    }

    if(symbol == ''){
        return false;
    }        

    symbol = symbol.substr(symbol.length - 1, (symbol.length));        

    if($.isNumeric(symbol)){
        return false;    
    }

    var newSymbol = symbol.toLowerCase();

    if(symbol != newSymbol){
        return true;    
    }

    return false;

}

Функция принимает String значение для проверки.

/** 
* return boolean
* true - using Caps Lock
* false - not using Caps Lock
**/
function checkingUp(_obj){

    var symbol = _obj;

    if(symbol == ''){
        return false;
    }        

    symbol = symbol.substr(symbol.length - 1, (symbol.length));        

    if($.isNumeric(symbol)){
        return false;    
    }

    var newSymbol = symbol.toLowerCase();

    if(symbol != newSymbol){
        return true;    
    }

    return false;

}

Функция может быть использована для проверки вводимого значения в поле Password, примерный код проверки с использованием вышеизложенной функции прилаживая ниже . . .

    $("#login-form input[type=password]").each(function(){

        // после поля ввода пароля расположен span с логотипом капчи, скрытый стилями css
        var iconCapsLock = $(this).parent().find('.capslock');

        $(this).bind('keyup', function(){

             if(checkingUp($(this))){
                iconCapsLock.show();
             }
             else{
                iconCapsLock.hide();
             }
        });

        $(this).bind('blur', function(){
            iconCapsLock.hide();
        });

});

И под конец пример HTML верстки с полем для проверки

    <div class="form-group relative">
        <input type="password"name="RegistrationForm[user_password]" class="input-lg form-control">
<span class="help-block"><span aria-hidden="true" class="capslock glyphicon glyphicon-text-height"></span></span>
    </div>

Надеюсь, что мой совет поможет нуждающимся ))

Правда о регистре символов, которую должны знать программисты

Время на прочтение
9 мин

Количество просмотров 23K

На конференции North Bay Python в 2018 году я делал доклад об именах пользователей. Информация из доклада по большей части была собрана мною за 12 лет поддержки django-registration. Этот опыт дал мне гораздо больше знаний, чем я планировал получить, о том, насколько сложными могут быть «простые» вещи.

В начале доклада я, правда, упомянул, что это не будет очередное разоблачение из серии «заблуждения по поводу Х, в которые верят программисты». Таких разоблачений можно найти сколько угодно. Однако мне подобные статьи не нравятся. В них перечисляются разные вещи, якобы являющиеся ложными, однако очень редко объясняется – почему это так, и что нужно делать вместо этого. Подозреваю, что люди просто прочтут такие статьи, поздравят себя с этим достижением, и потом пойдут находить новые интересные способы делать ошибки, не упомянутые в этих статьях. Всё потому, что они на самом деле не поняли проблем, порождающих этих ошибки.

Поэтому в своём докладе я постарался как можно лучше объяснить некоторые проблемы и пояснить, как их решать – такой подход мне нравится гораздо больше. Одна из тем, которой я коснулся лишь вскользь (это был всего один слайд и пара упоминаний на других слайдах) – это сложности, которые могут быть связаны с регистром символов. Для задачи, которую я обсуждал – сравнение идентификаторов без учёта регистра – есть официальный Правильный Ответ™, и в докладе я дал лучшее из известных мне решений, использующее только стандартную библиотеку Python.

Однако я кратко упомянул о более глубоких сложностях с регистром символов в Unicode, и хочу посвятить некоторое время описанию подробностей. Это интересно, и понимание этого может помочь вам принимать решения при проектировании и написании кода, обрабатывающего текст. Поэтому предлагаю вам нечто противоположное статьям «заблуждения по поводу Х, в которые верят программисты» – «правда, которую должны знать программисты».

И ещё одно: в Unicode полно терминологии. В данной статье я буду использовать в основном определения «верхний регистр» и «нижний регистр», поскольку стандарт Unicode использует эти термины. Если вам нравятся другие термины, вроде строчная/прописная буквы – всё нормально. Также я часто буду использовать термин «символ», который некоторые могут счесть некорректным. Да, в Unicode концепция «символа» не всегда совпадает с ожиданиями людей, поэтому часто лучше избегать её, используя другие термины. Однако в данной статье я буду использовать этот термин так, как он используется в Unicode – для описания абстрактной сущности, о которой можно делать заявления. Когда это важно, для уточнения я буду использовать более конкретные термины типа «кодовой позиции» [code point].

Регистров бывает больше двух

Носители европейских языков привыкли к тому, что в их языках регистр символов используется для обозначения конкретных вещей. К примеру, в английском [и русском] языках мы обычно начинаем предложения с буквы в верхнем регистре, а продолжаем чаще всего буквами в нижнем регистре. Также имена собственные начинаются с букв в верхнем регистре, и многие акронимы и аббревиатуры записываются в верхнем регистре.

И мы обычно считаем, что регистров существует всего два. Есть буква «А», и есть буква «а». Одна в верхнем, другая в нижнем регистре – не правда ли?

Однако в Unicode есть три регистра. Есть верхний, есть нижний, и есть титульный регистр [titlecase]. В английском языке так записываются названия. Например, «Avengers: Infinity War». Обычно для этого первая буква каждого слова просто пишется в верхнем регистре (и в зависимости от разных правил и стилей, некоторые слова, например, артикли, не пишутся с заглавных букв).

В стандарте Unicode дан такой пример символа в титульном регистре: U+01F2 LATIN CAPITAL LETTER D WITH SMALL Z. Выглядит он так: Dz.

Подобные символы иногда требуются для обработки негативных последствий одного из ранних решений разработки стандарта Unicode: совместимости с существующими текстовыми кодировками в обе стороны. Для Unicode было бы удобнее составлять последовательности при помощи имеющихся у стандарта возможностей по комбинированию символов. Однако во многих уже существующих системах уже были отведены места для готовых последовательностей. К примеру, в стандарте ISO-8859-1 («latin-1») у символа «é» есть готовая форма, имеющая номер 0xe9. В Unicode предпочтительнее было бы писать эту букву при помощи отдельной «е» и знака ударения. Но для обеспечения полной совместимости в обе стороны с такими существующими кодировками, как latin-1, в Unicode также назначены кодовые позиции для готовых символов. К примеру, U+00E9 LATIN SMALL LETTER E WITH ACUTE.

Хотя кодовая позиция этого символа совпадает с его байтовым значением из latin-1, полагаться на это не стоит. Вряд ли кодирование символов в Unicode сохранит эти позиции. К примеру, в UTF-8 кодовая позиция U+00E9 записана в виде байтовой последовательности 0xc3 0xa9.

И, конечно, в уже существующих кодировках есть символы, которым требовалось особое обхождение при использовании титульного регистра, из-за чего они были включены в Unicode «как есть». Если хотите посмотреть на них, поищите в своей любимой базе Unicode символы из категории Lt («Letter, titlecase»).

Есть несколько способов определить регистр

В стандарте Unicode (§4.2) перечислено три разных определения регистра. Возможно, выбор одного из трёх за вас делает ваш язык программирования; в противном случае, ваш выбор будет зависеть от конкретной цели. Вот эти определения:

  1. Символ находится в верхнем регистре, если он принадлежит к категории Lu («Letter, uppercase»), и в нижнем регистре, если принадлежит к категории Ll («Letter, lowercase»). В стандарте признаётся ограниченность этого определения: каждый конкретный символ приходится относить только к одной из категорий. Из-за этого многие символы, которые «должны находиться» в верхнем или нижнем регистре не удовлетворят этому требованию потому, что принадлежат к какой-то другой категории.
  2. Символ находится в верхнем регистре, если он унаследовал свойство Uppercase, и в нижнем регистре, если унаследовал свойство Lowercase. Это комбинация определения один с другими свойствами символов, среди которых может быть и регистр.
  3. Символ находится в верхнем регистре, если после применения к нему регистрового отображения в верхний регистр он не меняется. Символ находится в нижнем регистре, если после применения к нему регистрового отображения в нижний регистр он не меняется. Довольно общее определение, однако и оно может вести себя неинутитивно.

Если вы работаете с ограниченным подмножеством символов (конкретно, с буквами), то вам может хватить и 1-го определения. Если ваш репертуар шире – в него входят похожие на буквы символы, не являющиеся буквами, вам может подойти 2-е определение. Его рекомендует и стандарт Unicode, §4.2:

Программистам, манипулирующим строками в Unicode, стоит работать с такими строковыми функциями, как isLowerCase (и её функциональным родственником toLowerCase), если они не работают со свойствами символов напрямую.

Упомянутая здесь функция определяется в §3.13 стандарта Unicode. Формально в 3-м определении используются функции isLowerCase и isUpperCase из §3.13, определяемые в терминах фиксированных позиций в toLowerCase и toUpperCase соответственно.

Если в вашем языке программирования есть функции для проверки или преобразования регистра строк или отдельных символов, стоит изучить, какие из упомянутых определений используются в реализации. Если вам интересно, то методы isupper() и islower() в Python используют 2-е определение.

Нельзя понять регистр символа по его внешнему виду или названию

По внешнему виду многих символов можно понять, в каком они регистре. К примеру, «А» находится в верхнем регистре. Это понятно и по названию символа: «LATIN CAPITAL LETTER A». Однако иногда такой метод не работает. Возьмём кодовую позицию U+1D34. Выглядит она так: ᴴ. В Unicode ей назначено имя: MODIFIER LETTER CAPITAL H. Значит, она в верхнем регистре, так?

На самом же деле она наследует свойство Lowercase, поэтому по определению №2 она находится в нижнем регистре, несмотря на то, что визуально напоминает заглавную Н, а в названии есть слово «CAPITAL».

У некоторых символов вообще нет регистра

Определение 135 в §3.13 стандарта Unicode гласит:

Символ С имеет регистр тогда и только тогда, когда у С есть свойство Lowercase или Uppercase, или значение параметра General_Category равно Titlecase_Letter.

Значит, очень много символов из Unicode – на самом деле, большая их часть – регистра не имеет. Не имеют смысла вопросы об их регистре, а изменения регистра на них не действуют. Однако мы можем получить ответ на этот вопрос по определению №3.

Некоторые символы ведут себя так, будто у них несколько регистров

Из этого следует, что если вы используете определение №3, и задаёте вопрос, находится ли символ без регистра в верхнем или нижнем регистре, вы получите ответ «да».

В стандарте Unicode даётся пример (таблица 4-1, строка 7) символа U+02BD MODIFIER LETTER REVERSED COMMA (который выглядит так: ʽ). У него нет унаследованных свойств Lowercase или Uppercase, он не принадлежит к категории Lt, поэтому регистра у него нет. При этом преобразование в верхний регистр его не меняет, и преобразование в нижний регистр его не меняет, поэтому по 3-му определению он отвечает «да» на оба вопроса: «принадлежишь ли ты к верхнему регистру?» и «принадлежишь ли ты к нижнему регистру?»

Кажется, что из-за этого может возникнуть никому не нужная путаница, однако смысл в том, что определение №3 работает с любой последовательностью символов Unicode, и позволяет упростить алгоритмы преобразования регистра (символы без регистра просто превращаются сами в себя).

Регистр зависит от контекста

Можно подумать, что если таблицы преобразования регистра в Unicode покрывают все символы, то это преобразование заключается просто в поиске нужного места в таблице. К примеру, в базе данных Unicode записано, что для символа U+0041 LATIN CAPITAL LETTER A нижним регистром будет U+0061 LATIN SMALL LETTER A. Просто, не так ли?

Один из примеров, в котором этот подход не работает – греческий язык. Символ Σ — то есть, U+03A3 GREEK CAPITAL LETTER SIGMA — сопоставлен двум разным символам при преобразовании в нижний регистр, в зависимости от того, где он находится в слове. Если он стоит на конце слова, тогда в нижнем регистре он будет ς (U+03C2 GREEK SMALL LETTER FINAL SIGMA). В любом другом месте это будет σ (U+03C3 GREEK SMALL LETTER SIGMA).

А это значит, что у регистра нет взаимной однозначности или транзитивности. Ещё один пример — ß (U+00DF LATIN SMALL LETTER SHARP S, или эсцет). В верхнем регистре это будет «SS», хотя теперь существует и другая его форма в верхнем регистре (ẞ, U+1E9E LATIN CAPITAL LETTER SHARP S). А при переводе «SS» в нижний регистр получается «ss», поэтому (используя терминологию стандарта Unicode для преобразования регистра): toLowerCase(toUpperCase(ß)) != ß.

Регистр зависит от локали

В разных языках правила преобразования регистра разные. Самый популярный пример: i (U+0069 LATIN SMALL LETTER I) и I (U+0049 LATIN CAPITAL LETTER I) в большинстве локалей преобразовываются друг в друга – в большинстве, но не во всех. В локалях az и tr (тюркские языки), i в верхнем регистре будет İ (U+0130 LATIN CAPITAL LETTER I WITH DOT ABOVE), а I в нижнем регистре будет ı (U+0131 LATIN SMALL LETTER DOTLESS I). Иногда правильная запись реально означает разницу между жизнью и смертью.

Сам Unicode не обрабатывает все возможные правила преобразования регистра для всех локалей. В базе данных Unicode есть только общие правила преобразования всех символов, не зависящие от локали. Также там есть особые правила для некоторых языков и составных форм – литовского языка, тюркских языков, некоторых особенностей греческого. Всего остального там нет. §3.13 стандарта упоминает это и рекомендует при необходимости вводить правила преобразования, зависящие от локали.

Один пример будет знаком англоговорящим – это титульный регистр определённых имён. «o’brian» нужно преобразовывать в «O’Brian» (а не в «O’brian»). Однако при этом «it’s» нужно преобразовывать в «It’s», а не в «It’S». Ещё один пример, который не обрабатывается в Unicode – это голландское буквосочетание «ij», которое при преобразовании в титульный регистр должно переходить в верхний регистр целиком, если стоит в начале слова. Таким образом, большой залив в Нидерландах в титульном регистре будет «IJsselmeer», а не «Ijsselmeer». В Unicode есть символы IJ U+0132 LATIN CAPITAL LIGATURE IJ и ij U+0133 LATIN SMALL LIGATURE IJ, если они вам нужны. По умолчанию преобразование регистра преобразует их друг в друга (хотя формы нормализации Unicode, использующие эквивалентность совместимости, разделят их на два отдельных символа).

Сравнение без учёта регистра требует приведения к сложенному регистру

Возвращаясь к материалу, представленному в докладе. Сложность работы с регистром в Unicode означает, что регистронезависимое сравнение нельзя проводить при помощи стандартных функций приведения к нижнему или верхнему регистру, имеющихся во многих языках программирования. Для таких сравнений в Unicode есть концепция приведения к сложенному регистру [case folding], а в §3.13 стандарта определяются функции toCaseFold и isCaseFolded.

Можно решить, что приведение к сложенному регистру похоже на приведение к нижнему регистру – но это не так. Стандарт Unicode предупреждает, что строка в сложенном регистре не обязательно будет находиться в нижнем регистре. В качестве примера приводится язык чероки – там в строке, находящейся в сложенном регистре, будут попадаться и символы в верхнем регистре.

На одном из слайдов моего доклада рекомендации Unicode Technical Report #36 реализуются на Python настолько полно, насколько это возможно. Проводится нормализация NFKC и потом для полученной строки вызывается метод casefold() (доступный только в Python 3+). И даже при этом некоторые крайние случаи выпадают, и это не совсем то, что рекомендуется для сравнения идентификаторов. Сначала плохие новости: Python не выдаёт наружу достаточно свойств Unicode для того, чтобы отфильтровать символы, которых нет в XID_Start или XID_Continue или символы, имеющие свойство Default_Ignorable_Code_Point. Насколько мне известно, он не поддерживает отображение NFKC_Casefold. Также в нём нет простого способа использовать модифицированный NFKC UAX #31§5.1.

Хорошие новости: большинство этих крайних случаев не связано с какими-либо реальными рисками безопасности, создаваемыми рассматриваемыми символами. И складывание регистра в принципе не определяется как операция, сохраняющая нормализацию (отсюда и отображение NFKC_Casefold, которое повторно нормализуется до NFC после складывания регистра). Как правило, при сравнении вас не волнует, будут ли обе строки нормализованы после предварительной обработки. Вас заботит, не противоречива ли предварительная обработка, и гарантирует ли она, что только строки, которые «должны» отличаться впоследствии, будут отличаться впоследствии. Если вас это беспокоит, вы можете вручную выполнить повторную нормализацию после сложения регистра.

Пока достаточно

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

Не будет ли наивной моя надежда на то, что другие люди перестанут писать разоблачения из серии «заблуждения по поводу Х, в которые верят программисты», и начнут уже писать статьи типа «правда, которую должны знать программисты»?

Понравилась статья? Поделить с друзьями:
  • Как найти алкен по молярной массе
  • Как найти клиентов на съем квартиры
  • Как найти выпуск реализованной продукции
  • Что значит подключение к пирам как исправить
  • Как найти вшей у человека