1

我需要一种算法(最好在 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 回答 4

4

从在 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é,删除不属于 GSM 字符集的á( ) 。\u00e1

于 2011-02-28T14:22:49.790 回答
1

听起来你需要一个编解码器。谷歌搜索出现了这个:http ://demo.sahanafoundation.org/gsoc2010/amishra/gsoc/modules/pygsm/gsmcodecs/ 我不知道它是否有效,你必须自己找出来。

该代码的许可证位于http://demo.sahanafoundation.org/gsoc2010/amishra/gsoc/modules/pygsm/LICENSE

编辑:嗨,这里是 pygsm 的贡献者(如果有任何疑问,请拨打文档字符串测试中的号码)。

仅供参考-上面链接的 Sahana 代码似乎已移至:http ://eden.sahanafoundation.org/browser#modules/pygsm/

此外,此 Sahana 代码源自https://github.com/developmentseed/slingshotSMS,它源自原始的独立库https://github.com/adammck/pygsm/ ...其许可证位于https ://raw.github.com/adammck/pygsm/master/LICENSE

于 2011-02-28T13:23:22.650 回答
0

第一个响应中的链接看起来可以解决问题;FWIW,我使用从这篇文章链接的库作为做类似事情的基础。

如您所见,作者创建了一个适合编码希腊语的编解码器,因此这只是一个起点。

您说要将“任意”字符串转换为其“最接近的等价物”;使其完全任意可能很困难,因为“最接近”在不同的域中可能具有不同的含义(例如,您如何处理 Unicode 雪人)?

如果您只是想处理拉丁字母或拉丁字母衍生的字母,那么“任意”应该是可行的。

于 2011-03-03T16:17:32.233 回答
0

这是我的 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
        }
    }
于 2018-08-22T19:37:57.520 回答