2014-08-28 2 views
2

Я помечал кодировку символов и текст, потому что знаю, если вы наберете 'and' == 'and' в консоль рельсов или большинство других языков программирования, вы получите true. Тем не менее, у меня возникла проблема, когда один из моих пользователей вставляет свой текст на мой сайт, я не могу проверить его правильно или проверить его оригинальность с помощью copyscape из-за некоторой проблемы с текстом. (Или, может быть, мое понимание кодировки текста?)Может ли кто-нибудь сказать мне, почему 'и' == 'и' ложно?

Пример:

Если скопировать и вставить следующую строку в консоли рельсы вы получите false.

'аnd' == 'and' #=> false 

Если скопировать и вставить следующую строку в консоли рельсы вы получите true, даже если они появляются точно так же в браузере.

'and' == 'and' #=> true 

Разница, в первом примере, первый 'аnd' копировании и вставке текста из моего пользователя, который вызывает проблемы. Все остальные экземпляры 'and' напечатаны в браузере.

Это проблема с кодировкой? Любые идеи о том, как исправить мою проблему?

Спасибо!

ответ

5

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

Первый символ первой строки не является «нормальным» a, это на самом деле U+0430 CYRILLIC SMALL LETTER A - первые два байта (208 и 176, или 0xD0 и 0xB0 в шестнадцатеричном формате) являются кодировка UTF-8, для этого символа , Это просто похоже на «нормальный» латинский a, который является U+0061 LATIN SMALL LETTER A.

Вот «нормальный» a: a, и это кириллица a: а, они выглядят в значительной степени идентичными.

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

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

Другим вариантом может быть выбор набора сценариев Unicode, поддерживаемых вашим приложением, и отказ от любых символов вне этих сценариев. Вы можете довольно легко проверить это с помощью поддержки регулярного выражения Ruby's, например. /\p{Cyrillic}/ будет соответствовать всем кириллицам.

+0

Черт бы тебя побрал! На 26 секунд быстрее! :-D +1 –

+0

Большое спасибо за прояснение этой проблемы для меня. Поскольку я запускаю сайт для публикации только на английском языке, я, вероятно, запрещаю символы вне выбранного набора сценариев Unicode. Я мог бы попробовать посмотреть, как идет перевод, но в любом случае большое спасибо вам! – user2726983

1

Я думаю, что это проблема с eccoding, у вас может быть такая попытка.

irb(main):010:0> 'and'.each_byte {|b| puts b} 
97 
110 
100 
=> "and" 

irb(main):011:0> 'аnd'.each_byte {|b| puts b} #copied and 
208 
176 
110 
100 
=> "аnd" 
+0

спасибо. Это полезно в том, что он отвечает на мой первый вопрос и позволяет мне знать, что мне нужно идти по пути исправления кодировки символов. Любые идеи о том, как исправить это в моем рубиновом коде? Или даже какую информацию мне нужно предоставить, чтобы получить более конкретный ответ? Я помечаю этот ответ как принятый, если я не получу ничего более конкретного, потому что он действительно отвечает на мой вопрос с заголовком. Благодаря! – user2726983

+0

@ user2726983 один 'а' - [кириллица] (http://en.wikipedia.org/wiki/A_ (кириллица)), он выглядит идентично, но имеет другую кодовую точку юникода. Это неправильная кодировка, просто неправильный символ. – Stefan

5

Проблема не в кодировании.Один файл или один терминал может иметь только одну кодировку. Если вы скопируете и вставляете обе строки в один и тот же исходный файл или одно и то же окно терминала, они будут вставлены с одинаковой кодировкой.

Проблема также не в нормализации или сгибании.

Первая строка имеет 4 октета: 0xD0 0xB0 0x6E 0x64. Первые два октета представляют собой двухоктовое кодирование UTF-8 одного кодового слова Unicode, третий и четвертый октеты - однооктевые кодировки UTF-8 кодовых точек Unicode.

Итак, строка состоит из трех кодов Unicode: U+0430 U+006E U+0064.

Эти три кодовые решения следующих трех символов:

  1. кириллице строчной буквы A
  2. Строчная латинская буква N
  3. Строчная латинская буква D

Вторая строка имеет 3 октета : 0x61 0x6E 0x64. Все три октета - это однооктевые кодировки UTF-8 кодовых точек Unicode.

Итак, строка состоит из трех кодов Unicode: U+0061 U+006E U+0064.

Эти три кодовые разрешения следующих трех персонажей:

  1. латинская буква А
  2. Строчная латинская буква N
  3. Строчная латинская буква D

Действительно, нет никаких проблем совсем! Две строки - разные. С помощью шрифта, который вы используете, кириллица a выглядит так же, как латинский a, но, что касается Unicode, это два разных символа. (И в другом шрифте они могут даже выглядеть по-другому!) Нет ничего, что можно сделать с точки зрения кодирования или Юникода, потому что проблема заключается не в кодировании, а в Unicode.

Это называется homoglyph, причем два символа отличаются друг от друга, но имеют одинаковые (или очень похожие) глифы.

Что вы могли попытаться сделать это транслитерации все строки в латинском (при условии, что вы можете гарантировать, что никто не хочет, чтобы ввести не-латинские символы), но на самом деле, вопросы:

  1. Где происходит ли это из кириллицы?
  2. Возможно, это было означает быть кириллицей a и действительно должен быть обработанным не равным латинскому a?

И в зависимости от ответов на эти вопросы вы можете либо исправить источник, либо просто ничего не делать.

Это очень горячая тема для поставщиков браузеров BTW, потому что в настоящее время кто-то может зарегистрировать домен google.com (с одной из букв, отключенных для homoglpyh), и вы не сможете определить разницу в адресе бар. Это называется атакой гомографа. Вот почему они всегда отображают домен Punycode в дополнение к доменному имени Unicode.

+0

Большое вам спасибо! Простите, это было через несколько секунд. Кроме того, ответ Мэтта был немного больше того, что я искал, но тогда у вас не было никакого способа узнать это, потому что мой вопрос был настолько расплывчатым. Спасибо чувак! – user2726983

Смежные вопросы