python-re 中的正则表达式条件提取
regex conditional extract in python-re
我正在尝试从错误文本中提取通常为 4 个整数的 SQLCODE,如下所示:
1. SQLSTATE: 22018, SQLCODE: 3535.
2. SQLSTATE: 40001, SQLCODE: 2631 Session Id 629709103
3. SQLSTATE: 40001, SQLCODE: 2631 Session Id 594700603
4. SQLSTATE: T7547, SQLCODE: 754Session Id613234380
我目前有以下相同的模式匹配正则表达式。但是,有像 4 这样的边缘案例失败了。
error_cd = re.findall(r'SQLCODE:\s([^.,\s]+)', err_log)
如果SQLCODE后面没有4个整数,我想提取字母'T'
后面的SQLSTATE文本
预期输出:
1. 3535
2. 2631
3. 2631
4. 7547
如有任何关于如何实现这一目标的建议,我们将不胜感激。谢谢。
这可能完全在正则表达式中完成,使用 lookahead/lookbehind 来处理条件提取,但这可能会变得非常混乱。
解决方案 1:纯正则表达式:
编辑:这是纯正则表达式的解决方案……比我想象的要简单(尽管肯定比混合方法更 error-prone……需要一些额外的逻辑来使其更健壮):
re.findall(r'((?:(?<=SQLSTATE: T)(?![0-9]{4}, SQLCODE: [0-9]{4})[0-9]{4})|(?:(?<=SQLCODE: )[0-9]{4}))', err_log)
解决方案 2:正则表达式和 Python:
以下解决方案使用正则表达式提取 SQLSTATE 和 SQLCODE 值,并使用列表推导式进行条件提取:
err_log = '''
1. SQLSTATE: 22018, SQLCODE: 3535.
2. SQLSTATE: 40001, SQLCODE: 2631 Session Id 629709103
3. SQLSTATE: 40001, SQLCODE: 2631 Session Id 594700603
4. SQLSTATE: T7547, SQLCODE: 754Session Id613234380
'''
error_st_cd = re.findall(r'SQLSTATE: +T([0-9]+), SQLCODE: +([0-9]{4})?', err_log)
error_cd = [codes[1] or codes[0] for codes in error_st_cd]
for i, cd in enumerate(error_cd):
print(f'{i+1}. {cd}')
输出:
- 3535
- 2631
- 2631
- 7547
正则表达式方法可能确实更简单,但无论如何,这里有一种方法w/o使用正则表达式:
test_string = """
1. SQLSTATE: 22018, SQLCODE: 3535.
2. SQLSTATE: 40001, SQLCODE: 2631 Session Id 629709103
3. SQLSTATE: 40001, SQLCODE: 2631 Session Id 594700603
4. SQLSTATE: T7547, SQLCODE: 754Session Id613234380
""".strip()
def process_lines(s: str):
for line in s.split('\n'):
sql_code = ''.join(take_nums(line.split('SQLCODE: ', 1)[-1]))
if len(sql_code) == 4:
yield sql_code
else:
sql_state = ''.join(take_nums(line.split('SQLSTATE: ', 1)[-1][1:]))
yield sql_state
def take_nums(s: str):
"""take from string only while we get space or numeric chars"""
for c in s:
if c.isnumeric():
yield c
elif not c.isspace():
break
for i, line in enumerate(process_lines(test_string), 1):
print(f'{i}. {line!r}')
结果:
1. '3535'
2. '2631'
3. '2631'
4. '7547'
我正在尝试从错误文本中提取通常为 4 个整数的 SQLCODE,如下所示:
1. SQLSTATE: 22018, SQLCODE: 3535.
2. SQLSTATE: 40001, SQLCODE: 2631 Session Id 629709103
3. SQLSTATE: 40001, SQLCODE: 2631 Session Id 594700603
4. SQLSTATE: T7547, SQLCODE: 754Session Id613234380
我目前有以下相同的模式匹配正则表达式。但是,有像 4 这样的边缘案例失败了。
error_cd = re.findall(r'SQLCODE:\s([^.,\s]+)', err_log)
如果SQLCODE后面没有4个整数,我想提取字母'T'
后面的SQLSTATE文本预期输出:
1. 3535
2. 2631
3. 2631
4. 7547
如有任何关于如何实现这一目标的建议,我们将不胜感激。谢谢。
这可能完全在正则表达式中完成,使用 lookahead/lookbehind 来处理条件提取,但这可能会变得非常混乱。
解决方案 1:纯正则表达式:
编辑:这是纯正则表达式的解决方案……比我想象的要简单(尽管肯定比混合方法更 error-prone……需要一些额外的逻辑来使其更健壮):
re.findall(r'((?:(?<=SQLSTATE: T)(?![0-9]{4}, SQLCODE: [0-9]{4})[0-9]{4})|(?:(?<=SQLCODE: )[0-9]{4}))', err_log)
解决方案 2:正则表达式和 Python:
以下解决方案使用正则表达式提取 SQLSTATE 和 SQLCODE 值,并使用列表推导式进行条件提取:
err_log = '''
1. SQLSTATE: 22018, SQLCODE: 3535.
2. SQLSTATE: 40001, SQLCODE: 2631 Session Id 629709103
3. SQLSTATE: 40001, SQLCODE: 2631 Session Id 594700603
4. SQLSTATE: T7547, SQLCODE: 754Session Id613234380
'''
error_st_cd = re.findall(r'SQLSTATE: +T([0-9]+), SQLCODE: +([0-9]{4})?', err_log)
error_cd = [codes[1] or codes[0] for codes in error_st_cd]
for i, cd in enumerate(error_cd):
print(f'{i+1}. {cd}')
输出:
- 3535
- 2631
- 2631
- 7547
正则表达式方法可能确实更简单,但无论如何,这里有一种方法w/o使用正则表达式:
test_string = """
1. SQLSTATE: 22018, SQLCODE: 3535.
2. SQLSTATE: 40001, SQLCODE: 2631 Session Id 629709103
3. SQLSTATE: 40001, SQLCODE: 2631 Session Id 594700603
4. SQLSTATE: T7547, SQLCODE: 754Session Id613234380
""".strip()
def process_lines(s: str):
for line in s.split('\n'):
sql_code = ''.join(take_nums(line.split('SQLCODE: ', 1)[-1]))
if len(sql_code) == 4:
yield sql_code
else:
sql_state = ''.join(take_nums(line.split('SQLSTATE: ', 1)[-1][1:]))
yield sql_state
def take_nums(s: str):
"""take from string only while we get space or numeric chars"""
for c in s:
if c.isnumeric():
yield c
elif not c.isspace():
break
for i, line in enumerate(process_lines(test_string), 1):
print(f'{i}. {line!r}')
结果:
1. '3535'
2. '2631'
3. '2631'
4. '7547'