Python,正则表达式拆分和特殊字符

11

如何正确地使用空格作为分隔符来拆分包含特殊字符句子的字符串?使用正则表达式的拆分方法无法得到期望的结果。

示例代码:

# -*- coding: utf-8 -*-
import re


s="La felicità è tutto" # "The happiness is everything" in italian
l=re.compile("(\W)").split(s)

print " s> "+s
print " wordlist> "+str(l)
for i in l:
    print " word> "+i

输出结果为:

 s> La felicità è tutto
 wordlist> ['La', ' ', 'felicit', '\xc3', '', '\xa0', '', ' ', '', '\xc3', '', '\xa8', '', ' ', 'tutto']
 word> La
 word>  
 word> felicit
 word> Ã
 word> 
 word> ?
 word> 
 word>  
 word> 
 word> Ã
 word> 
 word> ?
 word> 
 word>  
 word> tutto

我希望得到如下的输出:

 s> La felicità è tutto
 wordlist> ['La', ' ', 'felicità', ' ', 'è', ' ', 'tutto']
 word> La
 word>  
 word> felicità
 word>  
 word> è
 word>  
 word> tutto

需要注意的是,s是从另一个方法返回的字符串,因此我无法强制编码方式。

s=u"La felicità è tutto"

在官方的Python Unicode和正则表达式文档中,我没有找到一个令人满意的解释。

谢谢。

Alessandro


1
你正在使用非单词字符进行分割,这不仅包括空格,还包括(显然)带重音的字符。 - mpen
5个回答

16

您的正则表达式应该是(\s)而不是(\W),像这样:

l = re.compile("(\s)").split(s)

上述代码会给你想要的确切输出。但是,下面这行代码更有意义:

l = re.compile("\s").split(s)

这个方法以空白字符为分隔符并不会将所有的空格作为匹配结果返回。但你可能需要这些空格,所以我发布了两个答案。


谢谢,它可以打印单个单词。 为什么列表的打印包含Unicode十六进制代码而不是解码字符? - alexroat
它的目的是生成有效的Python代码,您可以将其复制并粘贴回去...由于您可能正在非Unicode环境下工作,因此它以最可移植的方式输出。 - porges
谢谢Andrew。你完全回答了我所有的疑问。 - alexroat
完成了,但我有一个进一步的问题:为什么\s ()[]-等字符不被视为分隔符? - alexroat
它们是正则表达式语法使用的字符。如果您想在出现 ] 时分隔字符串,您应该使用 ] 进行转义(就像在使用正则表达式进行模式匹配时一样)。欢迎来到 StackOverflow :) - Andrea Ambu
好的,也许我能理解,\W 包括所有非字母数字字符,\s 包含所有空白符。但是看起来 "à" 不被视为字母数字字符?我的猜测是使用每个单独的非字母数字字符([^a-zA-Z0-9_])和带重音的字符进行分割。你有什么想法吗? - alexroat

4
尝试为正则表达式定义编码:
l=re.compile("\W", re.UNICODE).split(s)

它不起作用,我已经尝试过了... 然而,Andrew Hare的解决方案很好。 - alexroat
是的,但它的行为类似于字符串分割(它会删除空格),而我想保留它们。 然而,re.UNICODE会破坏编码并改变一些字符。 - alexroat

3

使用Unicode正则表达式可以起作用,前提是您提供一个Unicode字符串(在提供的示例中没有)。请尝试以下内容:

s=u"La felicità è tutto" # "The happiness is everything" in italian
l=re.compile("(\W)",re.UNICODE).split(s)

print " s> "+s
print " wordlist> "+str(l)
for i in l:
    print " word> "+i

结果:

 s> La felicità è tutto
 wordlist> [u'La', u' ', u'felicit\xe0', u' ', u'\xe8', u' ', u'tutto']
 word> La
 word>  
 word> felicità
 word>  
 word> è
 word>  
 word> tutto

你的字符串s是以str类型创建的,很可能采用的是utf-8编码,这与unicode编码不同。


3

我认为在这种情况下使用正则表达式有些过度了。如果你只想在空格字符上拆分字符串,我建议使用该字符串的split方法。

s = 'La felicità è tutto'
words = s.split()

我的意图是保留列表中的空格,因此字符串分割对此并不有帮助,因为它会删除空格,并且不能像正则表达式分割那样完全可配置。 - alexroat
@alexroat:你为什么需要这些空格呢?你知道它们出现在每个单词(列表项)之间,你的算法不能在必要时添加它们吗? - mpen

0

经过对Andrew Hare答案的进一步测试,我发现()[]-等字符不再被视为分隔符,而我想将由字母数字值集合组成的单词(保留所有分隔符)拆分成扩展为重音字符的单词(即,在Unicode中标记为字母数字)。因此,kgiannakakis的解决方案更正确,但它缺少将字符串s转换为Unicode格式的转换。

以第一个示例的扩展为例:

# -*- coding: utf-8 -*-
import re
s="(La felicità è tutto)"#no explicit unicode given string (UTF8)
l=re.compile("([\W])",re.UNICODE).split(unicode(s,'utf-8'))#split on s converted to unicode from utf8

print " string> "+s
print " wordlist> "+str(l)
for i in l:
    print " word> "+i

现在的输出是:

 string> (La felicità è tutto)
 wordlist> [u'', u'(', u'La', u' ', u'felicit\xe0', u' ', u'\xe8', u' ', u'tutto', u')', u'']
 word> 
 word> (
 word> La
 word>  
 word> felicità
 word>  
 word> è
 word>  
 word> tutto
 word> )
 word> 

这正是我正在寻找的。

干杯:)

Alessandro


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