Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   ActionScript 3.0 (http://www.flasher.ru/forum/forumdisplay.php?f=83)
-   -   Регулярное выражение для диапазона Юникод (http://www.flasher.ru/forum/showthread.php?t=215673)

djken 21.11.2018 18:55

Регулярное выражение для диапазона Юникод
 
Вложений: 1
Всем привет!

Столкнулся с проблемой. Регулярное выражение не работает, если нужно искать символы в тексте на соответствие диапазону в Юникоде (т.к. диапазоны наверно работают только для символов)..

Например, регулярка для поиска суррогатных пар - а именно ищу в тексте иконки Эмоджи, которые выходят за пределы базовой мультиязычной плоскости BMP.
Код AS3:

var re:RegExp = new RegExp("([\ud800-\udbff])([\udc00-\udfff])", "g");

Пробую регулярку на JavaScript - работает.
И тут нормально работает
http://www.flasher.ru/forum/attachme...chmentid=33311

Уже голову ломаю не один день..
Буду признателен за любую подсказку в этом вопросе.

Добавлено через 5 часов 5 минут
Все таки диапазоны для юникода тоже работают.. Ищу в тексте иконку снеговика, которому соответствует код U+26с4 (2 байта)
Код AS3:

var str:String = "Найди ⛄️ меня!";
var re:RegExp = /[\u26c0-\u26cf]/g;
trace(str.match(re)); // выводит иконку снеговика ⛄️

Осталось понять, почему же не срабатывает поиск для более сложных емоджи, которые состоят из пары кодов (4 байта)...

caseyryan 22.11.2018 13:08

Скинь точный пример того что не работает. И точную регулярку, которую используешь для поиска.

djken 22.11.2018 18:39

caseyryan, вот.

Код AS3:

package
{
        import flash.display.Sprite;
        import flash.events.Event;
        import flash.net.URLLoader;
        import flash.net.URLRequest;
 
        public class Test extends Sprite
        {
                private var _json:Object;
                private var _text:String;
 
                public function Test()
                {
                        var ldr:URLLoader = new URLLoader();
                        ldr.addEventListener(Event.COMPLETE, onLoadComplete);
                        ldr.load(new URLRequest('https://www.instagram.com/p/xCZYTQLmlB/?__a=1'));
                }
 
                private function onLoadComplete(e:Event):void
                {
                        _json = JSON.parse(e.currentTarget.data);
                        _text = _json.graphql.shortcode_media.edge_media_to_caption.edges[0].node.text;
                        trace(_text);
 
                        var re:RegExp;
 
                        re = /\u26C4/g; // код иконки снеговика U+26C4
                        trace('1', _text.match(re)); // РАБОТАЕТ! Выводит снеговика
 
                        re = /[\u26C0-\u26CF]/g; // так же пробуем найти снеговика через диапазон кодов
                        trace('2', _text.match(re)); // РАБОТАЕТ! Выводит снеговика
 
                        re = /(\ud83c\udf84)/g; // теперь ищем иконку елки U+1F384. Т.к. это больше 2 байт, то записывается суррогатной парой - два подряд идущих кода - 2 старших байта U+D83C и 2 младших U+DF84
                        trace('3', _text.match(re)); // РАБОТАЕТ! Выводит елку
 
                        re = /([\ud800-\udbff][\udc00-\udfff])/g; //  снова ищем елку, но через диапазон. Диапазон всех суррогатных пар - старший U+D800 - U+DBFF и младший U+DC00 - U+DFFF
                        trace('4', _text.match(re)); // НЕ РАБОТАЕТ! Ничего не находит.
                }
        }
}


caseyryan 22.11.2018 21:54

Вложений: 1
Хз как это на 100% проверить, у меня в винде не отображаются эти эмодзи, но
я вижу, что твой код в принципе не может их искать. Если подумать, что он делает? Он пытается найти в однострочном тексте, с учетом регистра, один эмодзи, за которым сразу идет другой. При том ищет он не такую последовательность \ud898\udbff а просто \ud800 за которой идет еще одна такая же.
Сурогатные пары просто так не ищутся.
Попробуй написать так:
Код AS3:

re = /(\\[\w]{5}){2,4}/gi

Поясню что делает эта регулярка. Она ищет последовательность из одного обратного слеша, за которым сразу идут 5 словесных символов (чисел и/или букв). И указанная последовательность должна повторяться от 2 до 4 раз подряд
Получается вот так, если брать конкретно строку из твоего кода. Я не делал проверку именно диапазонов, потому что все равно не смогу проверить, из-за отсутствия эмодзи в тексте не своем компе)
Но если исходный код от инсты именно такой, как в том json, то моя регулярка без проблем его отрабатывает

djken 22.11.2018 23:10

Да, я понял что твоя регулярка делает, но в ActionScript тоже не работает... В это и проблема.. Почему так? :(( Хотя на JavaScript нормально срабатывает и на regex101.com

caseyryan 22.11.2018 23:33

Блин, да. Проверил. В as3 сразу парсятся эмодзи.
Сложно определить точный диапазон. На вскидку пришло малость костыльное, но всё же решение
Код AS3:

var regEx:RegExp = /[^\w,.;:!?\s]+/gi;

Просто ищем все то, что не является числом, буквой, знаком препинания или пробелом. И считаем, что это эмодзи.
Можно еще какие-то символы сюда добавить. Проверил, работает в as3

djken 22.11.2018 23:49

Ура!!! Вот такое решение нашел - работает! Находит все суррогатные пары :)

Код AS3:

package
{
        import flash.display.Sprite;
        import flash.events.Event;
        import flash.net.URLLoader;
        import flash.net.URLRequest;
 
        public class Test extends Sprite
        {
                private var _json:Object;
                private var _text:String;
 
                public function Test()
                {
                        var ldr:URLLoader = new URLLoader();
                        ldr.addEventListener(Event.COMPLETE, onLoadComplete);
                        ldr.load(new URLRequest('https://www.instagram.com/p/xCZYTQLmlB/?__a=1'));
                }
 
                private function onLoadComplete(e:Event):void
                {
                        _json = JSON.parse(e.currentTarget.data);
                        _text = _json.graphql.shortcode_media.edge_media_to_caption.edges[0].node.text;
                        var re:RegExp;
 
                        re = new RegExp("[" + generateRangeForUnicodeVariables(0xD800, 0xDBFF) + generateRangeForUnicodeVariables(0xDC00, 0xDFFF) + "]", "gi")
                        trace(_text.match(re));
                }
 
                private function generateRangeForUnicodeVariables(var1:Object, var2:Object):String
                {
                        return String.fromCharCode(var1) + "-" + String.fromCharCode(var2);
                }
        }
}



Часовой пояс GMT +4, время: 09:16.

Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.