
本文介绍多种从字符串中提取连续字母序列(即“单词”)的方法,重点解决按任意非字母字符分割的问题,兼顾 unicode 兼容性、简洁性与性能,适用于多语言文本处理。
本文介绍多种从字符串中提取连续字母序列(即“单词”)的方法,重点解决按任意非字母字符分割的问题,兼顾 unicode 兼容性、简洁性与性能,适用于多语言文本处理。
在自然语言处理、日志解析或文本清洗等场景中,我们常需从混杂标点、数字、空格甚至特殊符号的字符串中仅提取由字母组成的连续子串(即“单词”)。例如,给定字符串 "(This# is an5example!)",目标是得到 ['This', 'is', 'an', 'example'] —— 所有非字母字符(如 (、#、`、5、!`)均作为分隔符,且结果中不包含空字符串。
✅ 推荐方法:正则表达式(简洁、高效、Unicode 友好)
最直观且健壮的方式是使用 re.findall() 匹配 Unicode 字母序列:
import re s = "(This# is an5example!)" words = re.findall(r'[a-zA-Z]+', s) # 基础 ASCII 版本 print(words) # ['This', 'is', 'an', 'example']
但若需支持法语、德语、中文拼音、西里尔字母等国际化文本,应使用 Unicode 字母类 \p{L}(Python 3.12+ 原生支持),或兼容性更强的 re.findall(r'\w+', s) 配合 re.ASCII 标志排除下划线和数字——更稳妥的做法是显式使用 Unicode 属性(需 regex 第三方库):
# 推荐:使用标准库 + \w 并过滤下划线/数字(简单项目)
import re
words = [w for w in re.findall(r'\w+', s) if w.isalpha() and not w.isdigit()]
# 或安装 regex 库(支持 \p{L},推荐用于多语言)
# pip install regex
import regex
words = regex.findall(r'\p{L}+', s) # ✅ 正确匹配 'français'、'настройка' 等
⚠️ 注意:str.isalpha() 在处理组合字符(如带变音符号的 'franc\u0327ais')时可能返回 False,因其依赖 Python 对 Unicode 类别的实现,而该实现与标准 Unicode 定义存在差异。regex 库的 \p{L} 则严格遵循 Unicode 标准,更可靠。
✅ 替代方案:手动遍历(教学友好,可控性强)
对于学习目的或需精细控制逻辑(如保留大小写、跳过特定字符),可采用字符级遍历:
s = "(This# is an5example!)"
word_list = []
word = ""
for char in s:
if char.isalpha(): # 注意:此处仍受 isalpha() Unicode 限制
word += char
elif word: # 非空且遇到非字母字符 → 提交当前单词
word_list.append(word)
word = ""
# 收尾:防止字符串以字母结尾而遗漏
if word:
word_list.append(word)
print(word_list) # ['This', 'is', 'an', 'example']
该方法逻辑清晰,但需注意:
- char.isalpha() 对组合字符(如 ç 的分解形式 c + ◌̧)支持有限;
- 性能低于正则表达式,尤其对长文本;
- 不自动处理 Unicode 归一化(建议预处理:import unicodedata; s = unicodedata.normalize('NFC', s))。
✅ 进阶建议:统一预处理提升鲁棒性
为兼顾多语言与准确性,推荐组合使用:
import unicodedata
import regex # pip install regex
def extract_words(text: str) -> list:
# 归一化为 NFC 形式(合并组合字符)
normalized = unicodedata.normalize('NFC', text)
# 使用 Unicode 字母类精确匹配
return regex.findall(r'\p{L}+', normalized)
# 示例
print(extract_words("(This# is an5example!)")) # ['This', 'is', 'an', 'example']
print(extract_words("français naïve résumé")) # ['français', 'naïve', 'résumé']
print(extract_words("Привет, 世界!")) # ['Привет', '世界']
总结
| 方法 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| re.findall(r'[a-zA-Z]+', s) | 简单、内置、快 | 仅限 ASCII 字母 | 英文为主、无特殊字符 |
| re.findall(r'\w+', s) + 过滤 | 内置、易用 | 含数字/下划线,需后处理 | 快速原型 |
| regex.findall(r'\p{L}+', s) | Unicode 标准兼容、多语言安全 | 需额外安装 | 生产环境、国际化应用 |
| 手动遍历 | 逻辑透明、完全可控 | 易出错、性能低、Unicode 支持弱 | 教学、调试、极简依赖 |
选择方案时,请优先考虑文本的语言范围与可靠性要求。对于真实世界数据,regex 库配合 \p{L} 是最稳健的选择。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











