正则表达式可使用Python 3匹配以下划线开头和结尾的单词

时间:2019-03-05 20:52:34

标签: regex python-3.x

我有以下示例代码,其中我尝试用下划线(单引号或双引号)匹配所有以开始和结束的单词实例。

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___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方法的使用)?

2 个答案:

答案 0 :(得分:2)

如果您要匹配任何不以非单词字符(字母,数字和下划线以外的字符)开头和结尾的任意长度的字符字符(字母,数字和下划线),并且长度不限(甚至为1,{ {1}}),您可以使用

_

r'\b_(?:\w*_)?\b' 。参见regex demo

如果您不想匹配单字符单词(即re.findall),则需要删除可选的非捕获组,并使用_

如果您需要匹配至少3个字符,还可以将r'\b_\w*_\b'(零个或多个重复)替换为*(一个或多个出现)。

如果仅当单词在字符串的开头/结尾或后面有空格时才将它们视为整个单词,请将+替换为\b...\b

(?<!\S)...(?!\S)

请参见another regex demo

详细信息

  • r'(?<!\S)_\w*_(?!\S)' -单词边界,必须在字符串的开头或非单词char之前
  • \b-下划线
  • _-一个可选的非捕获组,匹配出现1或0次
    • (?:\w*_)?-0个以上的字符字符(字母,数字,\w*)(由于此可选组,甚至可以找到_个单词)
    • _-下划线
  • _-单词边界,必须在字符串末尾或非单词char后面
  • \b-左侧空白边界
  • (?<!\S)-正确的空白边界

请参见Python demo

(?!\S)

答案 1 :(得分:1)

您甚至不需要使用正则表达式,最有效的方法是将字符串拆分为单词,然后检查它是否以下划线开头和结尾。

def get_underscored(text):
    for word in text.split():
        if word.startswith("_") and word.endswith("_"):
            yield word

test = ['abc text_ abc',
'abc _text abc,',
'abc text_textUnderscored abc',
'abc :_text abc',
'abc _text_ abc',
'abc __text__ abc']
test_str = ' '.join(test)
print(list(get_underscored(test_str)))

结果是['_text_', '__text__']

允许这种方法在较大的输入上不像正则表达式那样可扩展,而在较小的输入上则可以快几个数量级。