簡體   English   中英

Python:如何在多行字符串中查找所有匹配項,但未按特定單詞開頭?

[英]Python: How to find all matches in a multiline string but not proceeded by particular word?

我有SQL代碼,我想在“插入”關鍵字之后提取表名。

基本上,我想使用以下規則進行提取:

  1. 包含單詞“插入”
  2. 后跟單詞“ into”(可選)
  3. 排除在insert into(可選)關鍵字之前的任何位置是否有“-”(SQL中的單行注釋)。
  4. 排除insert into(可選)關鍵字是否在“ / *”和“ * /”之間(在SQL中為多行注釋)。
  5. 插入(可選)關鍵字后,獲取下一個單詞(table_name)

例:

import re

lines = """begin insert into table_1 end
    begin insert table_2 end   
    select 1 --This is will not insert into table_3
    begin insert into
        table_4
    end
    /* this is a comment
    insert into table_5
    */
    insert into table_6
    """

p = re.compile( r'^((?!--).)*\binsert\b\s+(?:into\s*)?.*', flags=re.IGNORECASE | re.MULTILINE)
for m in re.finditer( p, lines ):
    line = lines[m.start(): m.end()].strip()

    starts_with_insert = re.findall('insert.*', line, flags=re.IGNORECASE|re.MULTILINE|re.DOTALL)
    print re.compile('insert\s+(?:into\s+)?', flags=re.IGNORECASE|re.MULTILINE|re.DOTALL).split(' '.join(starts_with_insert))[1].split()[0]

實際結果:

table_1
table_2
table_4
table_5
table_6

預期結果:由於table_5在/ *和* /之間,因此不應返回

table_1
table_2
table_4
table_6

有沒有一種優雅的方法可以做到這一點?

提前致謝。

編輯 :感謝您的解決方案。 是否可以使用純正則表達式而不從原始文本中刪除行?

我想顯示可從原始字符串中找到表名的行號。

更新后的代碼如下:

import re

lines = """begin insert into table_1 end
    begin insert table_2 end   
    select 1 --This is will not insert into table_3
    begin insert into
        table_4
    end
    /* this is a comment
    insert into table_5
    */
    insert into table_6
    """

p = re.compile( r'^((?!--).)*\binsert\b\s+(?:into\s*)?.*', flags=re.IGNORECASE | re.MULTILINE)
for m in re.finditer( p, lines ):
    line = lines[m.start(): m.end()].strip()
    line_no = str(lines.count("\n", 0, m.end()) + 1).zfill(6)

    table_names = re.findall(r'(?:\binsert\s*(?:into\s*)?)(\S+)', line, flags=re.IGNORECASE|re.MULTILINE|re.DOTALL)
    print '[line number: ' + line_no + '] ' + '; '.join(table_names)

嘗試使用lookahead / lookbehind排除/ *和* /之間的那些,但未產生我的預期結果。

感謝您的幫助。 謝謝!

使用re.sub()re.findall()函數re.findall()

# removing single line/multiline comments
stripped_lines = re.sub(r'/\*[\s\S]+\*/\s*|.*--.*(?=\binsert).*\n?', '', lines, re.S | re.I)

# extracting table names preceded by `insert` statement 
tbl_names = re.findall(r'(?:\binsert\s*(?:into\s*)?)(\S+)', stripped_lines, re.I)
print(tbl_names)

輸出:

['table_1', 'table_2', 'table_4', 'table_6']
import re
import string

lines = """begin insert into table_1 end
    begin insert table_2 end
    select 1 --This is will not insert into table_3
    begin insert into
        table_4
    end
    /* this is a comment
    insert into table_5
    */
    insert into table_6
    """

# remove all /* */ and -- comments
comments = re.compile('/\*(?:.*\n)+.*\*/|--.*?\n', flags=re.IGNORECASE | re.MULTILINE)
for comment in comments.findall(lines):
    lines = string.replace(lines, comment, '')

fullSet = re.compile('insert\s+(?:into\s+)*(\S+)', flags=re.IGNORECASE | re.MULTILINE)
print fullSet.findall(lines)

['table_1', 'table_2', 'table_4', 'table_6']

暫無
暫無

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

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