2014-05-21 8 views
1

J'ai un fichier qui contient entre autres des commandes SQL-CREATE-TABLE. Je veux écrire toutes les commandes SQL-CREATE-TABLE dans une liste (pas encore implémentée), chaque commande dans une entrée de liste séparée.Python - Regex, correspondance multiple

Mon problème est, que l'expression régulière ne renvoie que la première correspondance, mais il devrait y avoir plus.

Fichier source:

abcd 
something 
CREATE TABLE schema.test1(attribute1 DECIMAL(28, 7) NULL , 
ATTRIBUTE2 DECIMAL(28, 7) KEY NOT NULL , 
ATTRIBUTE3 DECIMAL(28, 7) NOT NULL , 
SET("db_alias_name" = 'TEST') 
; 

efgh 
something else 
CREATE TABLE schema.test2(attribute1 DECIMAL(28, 7) NULL , 
ATTRIBUTE2 DECIMAL(28, 7) KEY NOT NULL , 
ATTRIBUTE3 DECIMAL(28, 7) NOT NULL , 
SET("db_alias_name" = 'TEST') 
; 

something else 
CREATE TABLE schema.test3(attribute1 DECIMAL(28, 7) NULL , 
ATTRIBUTE2 DECIMAL(28, 7) KEY NOT NULL , 
ATTRIBUTE3 DECIMAL(28, 7) NOT NULL , 
SET("db_alias_name" = 'TEST') 
; 
something else 
12346 
higkl 

Mon script ne retourne que le premier match:

CREATE TABLE schema.test1(attribute1 DECIMAL(28, 7) NULL , 
ATTRIBUTE2 DECIMAL(28, 7) KEY NOT NULL , 
ATTRIBUTE3 DECIMAL(28, 7) NOT NULL , 
SET("db_alias_name" = 'TEST') 

Script:

# -*- coding: utf-8 -*- 
import os 
import re 

create_table_parts = [] 

atlfile = 'example.txt' 
data = '' 

def read_file(afile): 
    with open(afile) as atl: 
     text = atl.read() 
     return text 

data = read_file(atlfile) 
data_utf8 = unicode(data, "utf-8") 

round1 = re.search(r"(CREATE\sTABLE).+?(?=;)", data_utf8, re.MULTILINE|re.DOTALL) 
print round1.group() 

Pourriez-vous peut-être me dire, quel est le problème ici?

+1

Vous pourriez bénéficier de l'utilisation d'un analyseur au lieu de compter sur r expressions egulaires. https://github.com/andialbrecht/sqlparse –

+0

Merci pour l'indice – royskatt

Répondre

2

Vous seriez mieux d'utiliser finditer car elle retourne un objet match comme search:

someIter = re.finditer(r"(CREATE\sTABLE).+?(?=;)", data_utf8, re.MULTILINE|re.DOTALL) 
for mObj in someIter: 
    # process mObj 
+0

Merci, ça l'a fait! – royskatt

1

Vous pouvez utiliser à la place findall, voir https://docs.python.org/2/library/re.html#re.findall

+0

Pour une raison quelconque, l'anticipation positive ne fonctionne pas avec re.findall, elle renvoie uniquement la première partie de l'expression rationnelle: print re.findall (r "(CREATE \ sTABLE) +.? (? =;)", data_utf8, re.MULTILINE | re.DOTALL) Retours: [u'CREATE TABLE, u'CREATE TABLE, u'CREATE TABLE » ] – royskatt

+0

Il suffit d'utiliser cette regex au lieu de '' CREATE \ sTABLE. +? (? =;) '' –

0

Merci à la pointe de Mark, ci-dessous maintenant un exemple de travail solution:

# -*- coding: utf-8 -*- 
import os 
import re 

create_table_parts = [] 
atlfile = 'example.txt' 
data = '' 

def read_file(afile): 
    with open(afile) as atl: 
     text = atl.read() 
     return text 

data = read_file(atlfile) 
data_utf8 = unicode(data, "utf-8") 


def round1_get_CT(text): 
    match_list = [] 
    someIter = re.finditer(r"(CREATE\sTABLE).+?(?=;)", text, re.MULTILINE|re.DOTALL) 
    for mObj in someIter: 
     #print mObj.group() 
     match_list.append(mObj.group()) 
    return match_list 

create_table_parts = round1_get_CT(data_utf8) 

print "\n".join(create_table_parts)