簡體   English   中英

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

任何有關如何實現這一目標的建議都值得贊賞。 謝謝你。

這可能完全可以在正則表達式中完成,使用前瞻/后瞻來處理條件提取,但這可能會變得非常混亂。

解決方案 1:純正則表達式:

編輯:這是純正則表達式解決方案......比我想象的要簡單(雖然肯定比混合方法更容易出錯......需要一些額外的邏輯來使其更健壯):

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}')

輸出:

  1. 3535
  2. 2631
  3. 2631
  4. 7547

正則表達式方法可能確實更容易,但無論如何,這是一種不使用正則表達式的方法:

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'

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM