<?xml version="1.0" encoding="utf-8"?> 
<rss version="2.0"
  xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd"
  xmlns:atom="http://www.w3.org/2005/Atom">

<channel>

<title>Блог Артёма Агасиева: заметки с тегом Unicode</title>
<link>https://agasiev.com/tags/unicode/</link>
<description>Telegram: @aagasiev</description>
<author>Артём Агасиев</author>
<language>ru</language>
<generator>E2 (v3576; Aegea)</generator>

<itunes:owner>
<itunes:name>Артём Агасиев</itunes:name>
<itunes:email></itunes:email>
</itunes:owner>
<itunes:subtitle>Telegram: @aagasiev</itunes:subtitle>
<itunes:image href="" />
<itunes:explicit></itunes:explicit>

<item>
<title>Шпаргалка по формам/алгоритмам нормализации Unicode текста</title>
<guid isPermaLink="false">70</guid>
<link>https://agasiev.com/all/unicode-normal-forms-python/</link>
<pubDate>Sun, 06 Sep 2020 17:42:26 +0300</pubDate>
<author>Артём Агасиев</author>
<comments>https://agasiev.com/all/unicode-normal-forms-python/</comments>
<description>
&lt;p&gt;Алгоритмы нормализации в Unicode нужны для преобразования внутренней структуры текста, чтобы потом с ним было проще работать. Например, можно заменить &lt;a href="https://ru.wikipedia.org/wiki/Комбинируемый_символ"&gt;несколько символов одним&lt;/a&gt;, убрать все диакритические знаки из текста и даже преобразовать похожие буквы в их аналоги.&lt;/p&gt;
&lt;p&gt;Всего есть четыре таких алгоритма: NFD, NFC, NFKD, NFKC. Каждый в отдельности можно запускать на одной и той же строке много раз, и результат от этого никак не изменится. То есть они &lt;a href="https://ru.wikipedia.org/wiki/Идемпотентность"&gt;идемпотентны&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Работать с Unicode текстом будем при помощи страндартной Python библиотеки &lt;a href="https://docs.python.org/3/library/unicodedata.html"&gt;unicodedata&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;1. NFD (Normalization Form Canonical Decomposition) или форма нормализации D.&lt;/h2&gt;
&lt;p&gt;Раскладывает составные символы на несколько простых в соответствии с таблицами декомпозиции. Если хотя бы один из получившихся символов тоже составной, раскладываем и его до тех пор, пока не получим последовательность простых символов. То есть, алгоритм работает рекурсивно.&lt;/p&gt;
&lt;p&gt;Получившаяся разложенная последовательность сортируется в некотором порядке, пока не очень понял в каком именно.&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;for c in unicodedata.normalize(&amp;quot;NFD&amp;quot;, &amp;quot;ё&amp;quot;):
    print(&amp;quot;'%s': %s&amp;quot; % (c, unicodedata.name(c)))

&amp;gt;&amp;gt; 'е': CYRILLIC SMALL LETTER IE
&amp;gt;&amp;gt; '̈': COMBINING DIAERESIS&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Так можно быстро подчистить всю диакритику в тексте, удаляя все ненужные группы символов из строки и оставляя только буквы.&lt;/p&gt;
&lt;h2&gt;2. NFC (Normalization Form Canonical Composition) или форма нормализации C.&lt;/h2&gt;
&lt;p&gt;Сначала выполняет NFD декомпозицию, а затем комбинирует полученные простые символы в составные. NFD декомпозиция тут нужна, чтобы разбить уже частично комбинированные символы на простые составляющие для последующей сортировки и обратной сборки.&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;for c in unicodedata.normalize(&amp;quot;NFC&amp;quot;, &amp;quot;ё&amp;quot;):
    print(&amp;quot;'%s': %s&amp;quot; % (c, unicodedata.name(c)))

&amp;gt;&amp;gt; 'ё': CYRILLIC SMALL LETTER IO&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Так можно быстро «приклеить» всю диакритику к буквам и получить из двух символов CYRILLIC SMALL LETTER IE и COMBINING DIAERESIS один CYRILLIC SMALL LETTER IO.&lt;/p&gt;
&lt;h2&gt;3. NFKD (Normalization Form Compatibility Decomposition) или форма нормализации KD.&lt;/h2&gt;
&lt;p&gt;Алгоритм, который выполняет NFD декомпозицию и заменяет похожие символы совместимыми аналогами, например, дробь ’¼’ заменяется на строку символов «1/4».&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;s = '⑲ ⁹ ¼'
print(unicodedata.normalize(&amp;quot;NFKD&amp;quot;, s))

&amp;gt;&amp;gt; 1 19 9 1/4

for c in list(s):
    print(&amp;quot;'%s': %s - '%s'&amp;quot; % (c, unicodedata.name(c), unicodedata.normalize(&amp;quot;NFKD&amp;quot;, c)))

&amp;gt;&amp;gt; '⑲': CIRCLED NUMBER NINETEEN - '19'
&amp;gt;&amp;gt; ' ': SPACE - ' '
&amp;gt;&amp;gt; '⁹': SUPERSCRIPT NINE - '9'
&amp;gt;&amp;gt; ' ': SPACE - ' '
&amp;gt;&amp;gt; '¼': VULGAR FRACTION ONE QUARTER - '1⁄4'&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;После такой нормализации можно легко делать фильтрацию текста регэкспами, если его пытались усложнить и замаскировать от этого заменой похожих символов.&lt;/p&gt;
&lt;h2&gt;4. NFKC (Normalization Form Compatibility Composition) или форма нормализации KC.&lt;/h2&gt;
&lt;p&gt;Сначала выполняется совместимое разложение NFKD, а затем символы собираются вместе согласно NFC. Аналогично работе с NFC, можно быстро склеить всю диакритику с буквами, приведенными к некоторому базовому виду.&lt;/p&gt;
&lt;h2&gt;Проблемы NFKD и NFKC&lt;/h2&gt;
&lt;p&gt;При всем удобстве алгоритмов NFKD и NFKC, они не приводят некоторую часть визуально похожих символов к совместимым аналогам. Например, группу &lt;b&gt;Negative Circled Number &lt;/b&gt;* из блока &lt;a href="https://unicode-table.com/en/blocks/enclosed-alphanumerics/"&gt;Enclosed Alphanumerics&lt;/a&gt; вполне можно привести к числам, но этого не происходит:&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;unicodedata.normalize(&amp;quot;NFKC&amp;quot;, &amp;quot;⓫ ⓯&amp;quot;)

&amp;gt;&amp;gt; '⓫ ⓯'&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;А значит, если хочется сделать качественное приведение похожих символов, необходимое для многих задач, придется повозиться над своими таблицами замен.&lt;/p&gt;
</description>
</item>

<item>
<title>mysqldump с учетом UTF-8</title>
<guid isPermaLink="false">38</guid>
<link>https://agasiev.com/all/mysqldump-s-uchetom-utf-8/</link>
<pubDate>Mon, 30 Jul 2018 12:37:27 +0300</pubDate>
<author>Артём Агасиев</author>
<comments>https://agasiev.com/all/mysqldump-s-uchetom-utf-8/</comments>
<description>
&lt;p&gt;Если мы хотим сделать дамп базы MySQL и сохранить весь utf-8 набор символов, включая эмоджи и прочие радости жизни, то использовать такой классический пример будет очень плохой идеей:&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;mysqldump -u username -p database &amp;gt; db.dump&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Так уже лучше, но эта команда сдампит только utf8, но не utf8mb4:&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;mysqldump -u username -p database -r db.dump&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;А вот так, будет совсем хорошо:&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;mysqldump -u username -p database --default-character-set=utf8mb4 --result-file=db.dump&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Теперь, базу нужно импортировать на новое место.&lt;/p&gt;
&lt;p&gt;Так — плохо:&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;mysql -u username -p database &amp;lt; db.dump&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;А вот так — хорошо:&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;$ mysql -u username -p --default-character-set=utf8mb4 database
mysql&amp;gt; SOURCE db.dump&lt;/code&gt;&lt;/pre&gt;</description>
</item>


</channel>
</rss>