一个匹配区域指示字符类的Python正则表达式

7
我在Mac上使用Python 2.7.10。表情符号中的旗帜由一对区域指示符号表示。我想编写一个Python正则表达式,在一串表情符号旗帜之间插入空格。
例如,这个字符串是两个巴西国旗: u"\U0001F1E7\U0001F1F7\U0001F1E7\U0001F1F7"
它会呈现为:
我想在任何一对区域指示符号之间插入空格。类似于这样:
re.sub(re.compile(u"([\U0001F1E6-\U0001F1FF][\U0001F1E6-\U0001F1FF])"),
       r"\1 ", 
       u"\U0001F1E7\U0001F1F7\U0001F1E7\U0001F1F7")

...这将导致:

u"\U0001F1E7\U0001F1F7 \U0001F1E7\U0001F1F7 "

...但是那段代码给了我一个错误:

sre_constants.error: bad character range

我认为这是出错的提示,以下内容显示\U0001F1E7在正则表达式中被分成了两个“字符”:

re.search(re.compile(u"([\U0001F1E7])"),
          u"\U0001F1E7\U0001F1F7\U0001F1E7\U0001F1F7").group(0)

这将导致:
u'\ud83c'

很遗憾,我的Unicode理解能力还不足以让我继续深入了解。


3
你的第一次尝试在Python 3.5.1中会给你返回“ ”。 - Psidom
这段代码在Arch Linux上的Python2.7中运行正常。 - Aran-Fey
在大多数Python 3.x版本中,这已经不再是一个问题。您的代码应该断言sys.maxunicode大于等于1114111(宽字符编码),而不是65535(窄字符编码)。请参阅Python中的Unicode - 只有UTF-16吗? - smci
1个回答

11

我认为你正在使用Windows或Mac中的Python 2.7,该版本采用了狭窄的16位Unicode构建 - Linux/Glibc通常具有32位完整的unicode,此外Python 3.5在所有平台上都具有广泛的Unicode。

你看到的是一个代码被拆分成代理对。不幸的是,这也意味着你不能轻松地使用单个字符类来完成此任务。然而,仍然有可能。 U+1F1E6 () 的UTF-16表示形式是\uD83C\uDDE6,而U+1F1FF ()的UTF-16表示形式是\uD83C\uDDFF

我甚至没有访问这种Python构建的权限,但你可以尝试

\uD83C[\uDDE6-\uDDFF]

作为单个[\U0001F1E6-\U0001F1FF]的替换,因此您的整个正则表达式应为

(\uD83C[\uDDE6-\uDDFF]\uD83C[\uDDE6-\uDDFF])

字符类不起作用的原因是它试图从第一个代理对的后半部分到第二个代理对的前半部分建立一个范围 - 这会失败,因为范围的开头在字典上比结尾大。

然而,即使如此,此正则表达式在Linux上仍无法工作,因为Linux构建默认使用宽Unicode,你需要在Linux上使用原始正则表达式。


或者,将您的Windows Python 升级到3.5或更高版本。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接