我希望regEx匹配一些包含字母和数字字符的文本。但我不希望它只匹配alpha或数字。 例如。在python:
s = '[mytaskid: 3fee46d2]: STARTED at processing job number 10022001'
# ^^^^^^^^ <- I want something that'll only match this part.
import re
rr = re.compile('([0-9a-z]{8})')
print 'sub=', rr.sub('########', s)
print 'findall=', rr.findall(s)
生成以下输出:
sub= [########: ########]: STARTED at ########ng job number ########
findall= ['mytaskid', '3fee46d2', 'processi', '10022001']
我希望它是:
sub= [mytaskid: ########]: STARTED at processing job number 10022001
findall= ['3fee46d2']
任何想法......?
在这种情况下,它总是只有8个字符,如果有一个没有{8}
的regEx会更加精彩,即即使有多于或少于8个字符。
- 编辑 -
问题更多的是要了解是否有办法编写一个regEx,这样我就可以组合2个模式(在本例中为[0-9]
和[a-z]
)并确保匹配的字符串匹配两种模式,但从每组匹配的字符数是可变的。例如。 s也可以
s = 'mytaskid 3fee46d2 STARTED processing job number 10022001'
- 回答 -
感谢大家的答案,所有人都给了我想要的东西,所以每个人都获得+1,第一个回答得到了接受的答案。虽然杰里解释得最好。 :)
如果有人是表演的坚持者,没有什么可供选择的,他们都是一样的。
s = '[mytaskid: 3fee46d2]: STARTED at processing job number 10022001'
# ^^^^^^^^ <- I want something that'll only match this part.
def testIt(regEx):
from timeit import timeit
s = '[mytaskid: 3333fe46d2]: STARTED at processing job number 10022001'
assert (re.sub('\\b(?=[a-z0-9]*[0-9])[a-z0-9]*[a-z][a-z0-9]*\\b', '########', s) ==
'[mytaskid: ########]: STARTED at processing job number 10022001'), '"%s" does not work.' % regEx
print 'sub() with \'', regEx, '\': ', timeit('rr.sub(\'########\', s)', number=500000, setup='''
import re
s = '%s'
rr = re.compile('%s')
''' % (s, regEx)
)
print 'findall() with \'', regEx, '\': ', timeit('rr.findall(s)', setup='''
import re
s = '%s'
rr = re.compile('%s')
''' % (s, regEx)
)
testIt('\\b[0-9a-z]*(?:[a-z][0-9]|[0-9][a-z])[0-9a-z]*\\b')
testIt('\\b[a-z\d]*(?:\d[a-z]|[a-z]\d)[a-z\d]*\\b')
testIt('\\b(?=[a-z0-9]*[0-9])[a-z0-9]*[a-z][a-z0-9]*\\b')
testIt('\\b(?=[0-9]*[a-z])(?=[a-z]*[0-9])[a-z0-9]+\\b')
制备:
sub() with ' \b[0-9a-z]*(?:[a-z][0-9]|[0-9][a-z])[0-9a-z]*\b ': 0.328042736387
findall() with ' \b[0-9a-z]*(?:[a-z][0-9]|[0-9][a-z])[0-9a-z]*\b ': 0.350668751542
sub() with ' \b[a-z\d]*(?:\d[a-z]|[a-z]\d)[a-z\d]*\b ': 0.314759661193
findall() with ' \b[a-z\d]*(?:\d[a-z]|[a-z]\d)[a-z\d]*\b ': 0.35618526928
sub() with ' \b(?=[a-z0-9]*[0-9])[a-z0-9]*[a-z][a-z0-9]*\b ': 0.322802906619
findall() with ' \b(?=[a-z0-9]*[0-9])[a-z0-9]*[a-z][a-z0-9]*\b ': 0.35330467656
sub() with ' \b(?=[0-9]*[a-z])(?=[a-z]*[0-9])[a-z0-9]+\b ': 0.320779061371
findall() with ' \b(?=[0-9]*[a-z])(?=[a-z]*[0-9])[a-z0-9]+\b ': 0.347522144274
答案 0 :(得分:4)
尝试以下正则表达式:
\b[0-9a-z]*(?:[a-z][0-9]|[0-9][a-z])[0-9a-z]*\b
这将匹配包含数字后跟字母的单词,反之亦然。
因此,它将涵盖一整套包含至少一位数字和一个字母的单词。
注意:虽然不是python的情况,但我发现并非所有类型的工具都支持 lookahead 和 lookbehind 。所以我更愿意尽可能避免它们。
答案 1 :(得分:2)
您需要使用前瞻(?=...)
。
这个匹配[123]和[abc]中至少有一个的所有单词。
>>> re.findall('\\b(?=[abc321]*[321])[abc321]*[abc][abc321]*\\b', ' 123abc 123 abc')
['123abc']
这样你就可以对同一个字符串的约束进行AND。
>>> help(re)
(?=...) Matches if ... matches next, but doesn't consume the string.
另一种方法是将它接地并说:用[abc]中的一个和[123]中的一个表示字符串中至少有[123] [abc]或[abc] [123]在
>>> re.findall('\\b[abc321]*(?:[abc][123]|[123][abc])[abc321]*\\b', ' 123abc 123 abc')
['123abc']
答案 2 :(得分:2)
不是最美丽的正则表达式,但它有效:
\b[a-z\d]*(?:\d[a-z]|[a-z]\d)[a-z\d]*\b
答案 3 :(得分:1)
如果格式每次都相同,那就是:
[########: ########]: STARTED at ########ng job number ########
您可以使用:
([^\]\s]+)\]
使用re.findall
或re.search
,如果您使用.group(1)
,则会获得re.search
。
[^\]\s]+
是一个否定的类,将匹配除空格(和系列)或右方括号之外的任何字符。
正则表达式基本上会查找字符(]
或空格除外)直到结束方括号。
如果要匹配包含字母和数字字符的任何字符串,则需要前瞻:
\b(?=[0-9]*[a-z])(?=[a-z]*[0-9])[a-z0-9]+\b
像这样使用:
result = re.search(r'\b(?=[0-9]*[a-z])(?=[a-z]*[0-9])[a-z0-9]+\b', text, re.I)
re.I
用于忽略。
\b
是单词边界,仅匹配“单词”字符和“非单词”字符(或字符串的开头/结尾)。
(?=[0-9]*[a-z])
是一个积极的前瞻,并确保要匹配的部分中至少有1个alpha。
(?=[a-z]*[0-9])
是类似的前瞻,但会检查数字。
答案 4 :(得分:0)
您可以使用更具体的正则表达式并跳过findall。
import re
s = '[mytaskid: 3fee46d2]: STARTED at processing job number 10022001'
mo = re.search(':\s+(\w+)', s)
print mo.group(1)