Алгоритм преобразования юникода в символы gsm - PullRequest
1 голос
/ 28 февраля 2011

Мне нужен алгоритм (желательно на Python) для преобразования произвольной строки в строку, содержащую только символы из алфавита GSM. Мне нужен этот фильтр для отправки строки в виде текста в SMS: es. Если возможно, алгоритм должен также заменять символы их ближайшим кодируемым эквивалентом. Примеры:

>>> gsm_convert('© all rights reserved')
[copyright sign] all rights reserved
# or
C all rights reserved
>>> gsm_convert('––– long dashes –––')
--- long dashes ---

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

Ответы [ 4 ]

4 голосов
/ 28 февраля 2011

Делая это в Perl и PHP, я сделал бы это в два шага, используя регулярные выражения.

  • Начните с включения поддержки регулярных выражений

    import re
    
  • Замените любые символы, которые вы можете, их ближайшим соответствием.

    Я бы предложил использовать набор регулярных выражений, например, замените «á» на «a», используя следующее

    message = ur'abc\u00e9\u00e1'
    message = re.sub(ur'\u00e1','a',message)
    
  • Удалите все оставшиеся символы, которые не входят в набор символов GSM.

    message = ur'abc\u00e9\u00e1'    
    
    message = re.sub(ur'[^\u0040\u00A3\u0024\u00A5\u00E8\u00E9\u00F9\u00EC\u00F2\u00C7\u000A\u00D8\u00F8\u000D\u00C5\u00E5\u0394\u005F\u03A6\u0393\u039B\u03A9\u03A0\u03A8\u03A3\u0398\u039E\u00C6\u00E6\u00DF\u00C9\u0020\u0021\u0022\u0023\u00A4\u0025\u0026\u0027\u0028\u0029\u002A\u002B\u002C\u002D\u002E\u002F\u0030\u0031\u0032\u0033\u0034\u0035\u0036\u0037\u0038\u0039\u003A\u003B\u003C\u003D\u003E\u003F\u00A1\u0041\u0042\u0043\u0044\u0045\u0046\u0047\u0048\u0049\u004A\u004B\u004C\u004D\u004E\u004F\u0050\u0051\u0052\u0053\u0054\u0055\u0056\u0057\u0058\u0059\u005A\u00C4\u00D6\u00D1\u00DC\u00A7\u00BF\u0061\u0062\u0063\u0064\u0065\u0066\u0067\u0068\u0069\u006A\u006B\u006C\u006D\u006E\u006F\u0070\u0071\u0072\u0073\u0074\u0075\u0076\u0077\u0078\u0079\u007A\u00E4\u00F6\u00F1\u00FC\u00E0\u20AC\u005B\u005C\u005D\u005E\u007B\u007C\u007D\u007E]','',message)
    
    print message
    

В этом примере будет напечатано abcé, удалив á (\u00e1), который не является частью набора символов GSM.

1 голос
/ 28 февраля 2011

Похоже, вам нужен кодек.Погуглил это: http://demo.sahanafoundation.org/gsoc2010/amishra/gsoc/modules/pygsm/gsmcodecs/ Я понятия не имею, работает ли он, вам придется выяснить для себя.

Лицензия на этот код - http://demo.sahanafoundation.org/gsoc2010/amishra/gsoc/modules/pygsm/LICENSE

* 1007.* РЕДАКТИРОВАТЬ: Привет, автор статьи здесь (если есть сомнения, позвоните по номеру в тесте docstring).

FYI- Код Sahana, указанный выше, похоже, перемещен в:

Кроме того, этот код Sahana был получен из https://github.com/developmentseed/slingshotSMS,, который был получен из исходной автономной библиотеки https://github.com/adammck/pygsm/ ..., лицензия которой находится по адресу https://raw.github.com/adammck/pygsm/master/LICENSE

0 голосов
/ 22 августа 2018

Вот мой код C # (для французского текста)

    public static bool IsGsmString(string message)
    {
        // https://messente.com/documentation/tools/sms-length-calculator
        // https://stackoverflow.com/questions/29541753/regex-only-checks-first-character-in-string-c-sharp/29541980#29541977

        //var strMap = new Regex(@"^[@£$¥èéùìòÇØøÅå_ÆæßÉ!""#%&'()*+,./\w:;<=>? ¡ÄÖÑܧ¿äöñüà^{}\[~\]|€-]*$");
        //return !strMap.IsMatch(message.Replace(Environment.NewLine, ""));   // Enlever les saut de ligne car non inclus dans le Map

        foreach (char c in message.ToCharArray())
            if (!IsGsmChar(c))
                return false;

        return true;
    }

    public static bool IsGsmChar(char c)
    {
        string strGSMTable = "@£$¥èéùìòÇ`Øø`ÅåΔ_ΦΓΛΩΠΨΣΘΞ`ÆæßÉ !\"#¤%&'()*=,-./0123456789:;<=>?¡ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÑÜ`¿abcdefghijklmnopqrstuvwxyzäöñüà";
        strGSMTable += "^{}\\[~]|€" + Environment.NewLine;   // Adding extended char and CRLF

        return strGSMTable.IndexOf(c) >= 0;
    }

    public static string ReplaceNoneGsmChar(string message)
    {
        var converted = "";

        foreach (char c in message.ToCharArray())
        {
            if (IsGsmChar(c))
                converted += c;
            else
                converted += GsmReplacement(c);
        }

        return converted;
    }

    private static string GsmReplacement(char c)
    {
        switch (c)
        {
            case 'â':
                return "a";
            case 'ê':
            case 'ë':
                return "e";
            case 'î':
            case 'ï':
                return "i";
            case 'ô':
                return "o";
            case 'û':
                return "u";
            case 'ÿ':
                return "y";

            case 'Â':
            case 'À':
                return "A";
            case 'È':
            case 'Ê':
            case 'Ë':
                return "E";
            case 'Î':
            case 'Ï':
            case 'Ì':
                return "I";
            case 'Ô':
                return "I";
            case 'Ù':
            case 'Û':
                return "U";

            case '’':
            case '`':
                return "'";

            case '«':
            case '»':
                return @"""";

            case 'µ':
                return "u";
            case '©':
                return "C";
            case 'œ':
                return "oe";

            default:
                return "_";   // non remplacable
        }
    }
0 голосов
/ 03 марта 2011

Ссылка в первом ответе выглядит так, как будто она может сработать;FWIW, я использовал библиотеку, связанную с этого поста , как основу для выполнения чего-то подобного.

Как вы увидите, автор создал кодек, подходящий для кодирования греческого языка, так чтобудет просто отправной точкой.

Вы говорите, что хотите преобразовать «произвольную» строку в ее «ближайший эквивалент»;сделать его полностью произвольным может быть сложно, так как «самые близкие» могут иметь разные значения в разных областях (например, что вы делаете со снеговиком Юникод)?

Если вы просто пытаетесь разобраться с латынью или латиницей-производные алфавиты, тогда «произвольный» должен быть выполнимым.

...