首页 > 解决方案 > 正则表达式与 Python 3 匹配以下划线开头和结尾的单词

问题描述

我有以下示例代码,我试图匹配所有以下划线开头和结尾的单词实例(单或双)。

import re
test = ['abc text_ abc',
'abc _text abc',
'abc text_textUnderscored abc',
'abc :_text abc', 
'abc _text_ abc', 
'abc __text__ abc',
'abc _text_: abc',
'abc (-_-) abc']
test_str = ' '.join(test)
print(re.compile('(_\\w+\\b)').split(test_str))

我已经尝试过以下正则表达式,它似乎太强大了(应该只匹配_text_and __text__)。

输出:['abc text_ abc abc ', '_text', ' abc abc text', '_textUnderscored', ' abc abc :', '_text', ' abc abc ', '_text_', ' abc abc ', '__text__', ' abc abc ', '_text_', ': abc abc (-_-) abc']

你能建议一个更好的方法(最好是单一的正则表达式模式和re.split方法的使用)?

标签: regexpython-3.x

解决方案


如果您的意思是匹配任何非单词字符(字母、数字和下划线以外的字符)和任何长度(甚至是 1、_)的单词字符(字母、数字和下划线)块(字母、数字和下划线),您可以使用

r'\b_(?:\w*_)?\b'

re.findall. 请参阅正则表达式演示

如果您不想匹配单字符词(即_),则需要删除可选的非捕获组,并使用r'\b_\w*_\b'.

如果您需要匹配至少 3 个字符单词,也将*(零次或多次重复) 替换为+(一次或多次出现) 。

如果仅当单词位于字符串的开头/结尾或后面/前面有空格时才将单词视为整个单词,请替换\b...\b(?<!\S)...(?!\S)

r'(?<!\S)_\w*_(?!\S)'

查看另一个正则表达式演示

细节

  • \b- 单词边界,之前必须有字符串开头或非单词字符
  • _- 一个下划线
  • (?:\w*_)?- 一个可选的非捕获组匹配 1 或 0 次出现
    • \w*- 0+ 单词字符(字母、数字、_s)(感谢这个可选组,甚至_可以找到单词)
    • _- 一个下划线
  • \b- 单词边界,后面必须有字符串结尾或非单词字符
  • (?<!\S)- 左空白边界
  • (?!\S)- 右空白边界

请参阅Python 演示

rx = re.compile(r'\b_(?:\w*_)?\b')
print(rx.findall(test_str))
# => ['_text_', '__text__']

推荐阅读