我有以下示例代码,其中我尝试用下划线(单引号或双引号)匹配所有以开始和结束的单词实例。
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
方法的使用)?
答案 0 :(得分:2)
如果您要匹配任何不以非单词字符(字母,数字和下划线以外的字符)开头和结尾的任意长度的字符字符(字母,数字和下划线),并且长度不限(甚至为1,{ {1}}),您可以使用
_
与r'\b_(?:\w*_)?\b'
。参见regex demo。
如果您不想匹配单字符单词(即re.findall
),则需要删除可选的非捕获组,并使用_
。
如果您需要匹配至少3个字符,还可以将r'\b_\w*_\b'
(零个或多个重复)替换为*
(一个或多个出现)。
如果仅当单词在字符串的开头/结尾或后面有空格时才将它们视为整个单词,请将+
替换为\b...\b
:
(?<!\S)...(?!\S)
详细信息
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__']
。
允许这种方法在较大的输入上不像正则表达式那样可扩展,而在较小的输入上则可以快几个数量级。