簡體   English   中英

用於從嵌套組中選擇/提取的Python正則表達式

[英]Python regex for select/extract from nested groups

我正在嘗試使用CHAR(int)和NCHAR(int)處理一個字符串,以使用其ASCII計數器轉換這些實例。 一個例子是這樣的:

CHAR(124) + (SELECT TOP 1 CAST(name AS VARCHAR(8000)) FROM (SELECT TOP 1 colid, name FROM [Projects]..[syscolumns]
WHERE xtype=char(85)
AND id = OBJECT_ID(NCHAR(69)+NCHAR(78)+NCHAR(95)+NCHAR(69)+NCHAR(109)+NCHAR(112)+NCHAR(108))

請注意,我不想對VARCHAR(int)做任何事情,而只對CHAR(int)和NCHAR(int)部分做任何事情。 上面的應該翻譯為:

|(選擇頂部1個CAST(名稱為VARCHAR(8000)),來自(選擇頂部1個colid,名稱為[項目] .. [syscolumns]),其中xtype = U AND id = OBJECT_ID(EN_Empl)

請注意,應刪除CHAR(int)或NCHAR(int)兩側的任何“ +”號。 我嘗試了以下方法:

def conv(m):
    return chr(int(m.group(2)))

print re.sub(r'([\+ ]?n?char\((.*?)\)[\+ ]?)', conv, str, re.IGNORECASE)

其中str =必須處理的原始字符串。

不知何故,VARCHAR(8000)被拾取。 如果我調整正則表達式,則xtype之后的“ =”將會消失,而不僅僅是CHAR(int)或NCHAR(int)實例兩側的空格和“ +”。

希望有人可以把我從中拉出來。

其他示例字符串:

字符串"char(124)+(Select Top 1 cast(name as varchar(8000)) from (Select Top 1 colid,name From [Projects]..[syscolumns] Where id = OBJECT_ID(NCHAR(69)+NCHAR(78)+NCHAR(95)+NCHAR(69)+NCHAR(109)+NCHAR(112)+NCHAR(108)))"

正則表達式: r'(\\bn?char\\((\\d+)\\)(?:\\s*\\+\\s*)?)'

結果: "|(Select Top 1 cast(name as varchar(8000)) from (Select Top 1 colid,name From [Projects]..[syscolumns] Where id = OBJECT_ID(ENCHAR(78)+NCHAR(95)+NCHAR(69)+NCHAR(109)+NCHAR(112)+NCHAR(108)))"

您有三個問題:

  1. 您需要使用flags=re.IGNORECASE ,而不僅僅是re.sub中的 re.IGNORECASE 那是一個關鍵字參數。
  2. 您需要使用\\b查找單詞邊界。
  3. 請勿使用str作為名稱,因為您將用相同的名稱覆蓋內置文件

這有效:

import re

tgt='''\
CHAR(124) + (SELECT TOP 1 CAST(name AS VARCHAR(8000)) FROM (SELECT TOP 1 colid, name FROM [Projects]..[syscolumns]
WHERE xtype=char(85)
AND id = OBJECT_ID(NCHAR(69)+NCHAR(78)+NCHAR(95)+NCHAR(69)+NCHAR(109)+NCHAR(112)+NCHAR(108))'''

pat=r'(\bn?char\((\d+)\)(?:\s*\+\s*)?)'

def conv(m):
    return chr(int(m.group(2)))

print re.sub(pat, conv, tgt, flags=re.IGNORECASE)    

更完整地:

import re

tgt='''\
CHAR(124) + (SELECT TOP 1 CAST(name AS VARCHAR(8000)) FROM (SELECT TOP 1 colid, name FROM [Projects]..[syscolumns]
WHERE xtype=char(85)
AND id = OBJECT_ID(NCHAR(69)+NCHAR(78)+NCHAR(95)+NCHAR(69)+NCHAR(109)+NCHAR(112)+NCHAR(108))'''

pat=r'(\bn?char\((\d+)\)(?:\s*\+\s*)?)'

def conv(m):
    return chr(int(m.group(2)))

print re.sub(r'''
              (                                 # group 1
              \b                                # word boundary
              n?char                            # nchar or char
              \(                                # literal left paren
              (\s*\d+\s*)                       # digits surrounded by spaces
              \)                                # literal right paren
              (?:\s*\+\s*)?                     # optionally followed by a concating '+' 
              )                                 '''
            , conv, tgt, flags=re.VERBOSE | re.IGNORECASE)   

印刷品:

|(SELECT TOP 1 CAST(name AS VARCHAR(8000)) FROM (SELECT TOP 1 colid, name FROM [Projects]..[syscolumns]
WHERE xtype=U
AND id = OBJECT_ID(EN_Empl)

您只需添加單詞boundary( \\b )斷言就可以走很長一段路,但是我建議您(1)使用re.VERBOSE編寫一個以后可以理解的正則表達式; (2)編譯正則表達式以減少呼叫現場的混亂情況; (3)加強一些匹配標准。 像這樣:

def conv(m):
    return chr(int(m.group(1)))

pat = re.compile(r"""[+\s]*    # optional whitespace or +
                     \b        # word boundary
                     n?char    # NCHAR or CHAR
                     \(        # left paren
                     ([\d\s]+) # digits or spaces - group 1
                     \)        # right paren
                     [+\s]*    # optional whitespace or +
                  """, re.VERBOSE | re.IGNORECASE)
print pat.sub(conv, data)

請注意,我將您的str更改為datastr是一個經常使用的內置函數的名稱,創建具有相同名稱的變量是一個絕妙的主意。

您只需要使用單詞邊界\\b

def conv(m):
    return chr(int(m.group(1)))

print re.sub(r'\bn?char\(([^)]+)\)(?:\s*\+\s*)?', conv, str, re.IGNORECASE)

暫無
暫無

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

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