使用Python正则表达式进行单词分割

15

我正在尝试在Python中将字符串拆分为“标签”列表。拆分应该处理诸如“HappyBirthday”之类的字符串,删除大多数标点符号但保留连字符和撇号。我的起点是:

tags = re.findall("([A-Z]{2,}(?=[A-Z]|$)|[A-Z][a-z]*)|\w+-\w+|[\w']+"

I would want to turn this sample data:

Jeff's dog is un-American SomeTimes! BUT NOTAlways

Into:

['Jeff's', 'dog', 'is', 'un-American', 'Some', 'Times', 'BUT', 'NOT', 'Always']

抱歉我的描述可能不太好。我不确定如何解释,并且在谷歌上大多数情况下都没有成功。我希望示例可以恰当地说明问题。
编辑:我认为需要更精确,因此也有以下要求:
1.如果单词是连字号和大写字母的,比如“UN-American”,输出将保持为一个单词,因此输出为“UN-American”。 2.如果连字符两侧有空格,例如“THIS- is”或“This - is”,它应该忽略连字符并生成["THIS","is"]和["This","is"]。 3.同样,对于在单词中间的撇号,比如"What'sItCalled",应该生成["What's","It","Called"]。

2
通常这被称为标记化或“单词标记化”,而对于这个问题并没有普适的解决方案。我愿意接受不完美的解决方案。 - Kenan Banks
1
另一个问题是,对于像单词分词这样复杂的任务使用正则表达式可能会产生相对晦涩难懂的解决方案。 - Greg
无论是玄学的还是不玄学的,如果它能够正常工作,我就会很高兴,我并不在意是否理解它。 - user779420
2个回答

24

我建议如下:

re.findall("[A-Z]{2,}(?![a-z])|[A-Z][a-z]+(?=[A-Z])|[\'\w\-]+",s)

这适用于你的示例:

["Jeff's", 'dog', 'is', 'un-American', 'Some', 'Times', 'BUT', 'NOT', 'Always']

解释:RegExp由3个备选项组成:

  1. [A-Z]{2,}(?![a-z])匹配所有字母都是大写的单词
  2. [A-Z][a-z]+(?=[A-Z])匹配第一个字母大写的单词。先行断言(?=[A-Z])在下一个大写字母之前停止匹配。
  3. [\'\w\-]+匹配其余所有单词,即可能包含'-的单词。

如果单词中有连字符和大写字母,比如“UN-American”,那么翻译时是否保留连字符?对于“This-”或者“This-”这样的情况呢?甚至是“What'sItCalled”? - user779420
同时,如果“-”周围有空格,则应将其删除,即“this should - do that”转换为["this","should","do","that"]。 - user779420
如果您想删除单个连字符,或更一般地说是单个字母,您可以调用 filter(lambda s: len(s)>1, ...) 函数来处理字符串列表。 - phynfo
那么如果留下两个相邻的空格,会有影响吗?另外,你能给我提供一个解释吗?我不太熟悉这个。 - user779420

3
为了处理您编辑过的案例,我会修改Phynfo (+1)的优秀答案如下:
>>> s = """Jeff's UN-American Un-American un-American 
           SomeTimes! BUT NOTAlways This- THIS- 
           What'sItCalled someTimes"""
>>> re.findall("[A-Z\-\']{2,}(?![a-z])|[A-Z\-\'][a-z\-\']+(?=[A-Z])|[\'\w\-]+",s)
["Jeff's", 'UN-', 'American', 'Un-', 'American', 'un-American', 
 'Some', 'Times', 'BUT', 'NOT', 'Always', 'This-', 'THIS-', 
 "What's", 'It', 'Called' 'someTimes']

你必须清晰地定义所需行为的规则。仅进行标记化并不足够,你需要类似于phynfo的规则。例如,你可以制定一个规则,'NOTAlways'应该转换为'NOT''Always',并且连字符应该被保留。因此,'UN-American'会被分解成两个部分,就像UNAmerican一样被分解。你可以尝试定义其他规则,但必须清楚地说明当规则重叠时应用哪个规则。

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