1
votes

Remplacer l'occurrence interne d'une expression

Je travaille sur un morceau de code Python en utilisant des expressions régulières et j'essaye de réaliser ce qui suit:

Si j'ai un morceau de SQL sous forme de chaîne qui contient du code dans [] et une clause WHERE devant lui, je souhaite supprimer la clause WHERE complète. Par exemple:

txt = """where [Include_Fakes|TRUE] group by 1 order by 1,3 ) where signed_up_date >= dateadd('[aggregation]', -[Last_N_Periods|12], CURRENT_DATE)"""

expected output:
group by 1 order by 1,3 ) 

devient

"""where that and that do that group by 1,2,3"""

Le code que j'utilise est:

txt = """where that and that do that where [this = 1] and [that = 1] group by 1,2,3"""

Cependant, si j'ai une autre clause WHERE avant celle-ci, l'ensemble de l'expression régulière ne fonctionne pas comme prévu, par exemple:

where that and that do that group by 1,2,3

produit

group by 1,2,3

au lieu de

txt = """where that and that do that where [this = 1] group by 1,2,3"""

txt = re.sub("where.*\[.*\].*group" , 'group', txt, flags = re.S|re.I)  

Edit: la solution devrait également fonctionner pour un scénario comme celui-ci: p>

txt = """where [this = 1] group by"""

txt = re.sub("where.*\[.*\].*group" , 'group', txt, flags = re.S|re.I)    

renvoie:

group by 1,2,3

Donc, il supprime le code interne (le plus proche de [] ) Clause WHERE et tout le code contenant au moins un [] jusqu'à la prochaine GROUP , ORDER ou fin de chaîne .

Enfin, la solution doit prendre en charge les cas dans lesquels il existe plusieurs extraits de où .. [...] dans la chaîne. p>

where this condition and [this = 1] group by 1,2,3

Quelqu'un peut-il m'indiquer la bonne direction ici? Toute aide serait appréciée.


0 commentaires

3 Réponses :


1
votes

Voici un moyen de le faire.

exp =r"(where((?!where).)*\[.*?\].*?(?=(group|order)))|(where((?!where).)*\[.*?\].*$)"

txt = """where that and that do that where [this = 1] and [that = 1] group by 1,2,3"""
print(re.sub(exp, "", txt))
# ==> where that and that do that group by 1,2,3

txt = """where that and that do that where [this = 1] group by 1,2,3"""
print(re.sub(exp, "", txt))
# ==> where that and that do that group by 1,2,3

txt = """lots of code where signed_up_date >= dateadd('[aggregation]', -[Last_N_Periods|12], CURRENT_DATE)""" 
print(re.sub(exp, "", txt))
# ==> lots of code 

txt = """where [Include_Fakes|TRUE] group by 1 order by 1,3 ) where signed_up_date >= dateadd('[aggregation]', -[Last_N_Periods|12], CURRENT_DATE)"""
print(re.sub(exp, "", txt))

# ==> group by 1 order by 1,3 ) 

txt =  """where [condition1] group by 1) where [condition2] group by 2"""
print(re.sub(exp, "", txt))

# ==> group by 1) group by 2


19 commentaires

cela ne fonctionnerait pas si j'avais plusieurs [] , c'est-à-dire re.sub (r "where ((?! where).) *?] \ s?", "", " où cette condition et [this = 1] et [that = 1] group by 1,2,3 ") ne produit pas le résultat souhaité


Ce serait formidable si la question décrivait ce scénario, avec un exemple et les résultats attendus.


cela semble presque correct - cependant, cela ne fonctionne pas d'une manière ou d'une autre dans ce cas real_code = "" "beaucoup de code où signed_up_date> = dateadd ('[aggregation]', - [Last_N_Periods | 12], CURRENT_DATE)" " "reg = re.sub (r" où \ s + \ [. * \] \ s. * "," ", real_code, flags = re.S | re.I)


Qu'aimeriez-vous voir dans ce cas? Le crochet ne vient pas immédiatement après l'instruction "where".


"beaucoup de code" serait la sortie souhaitée. Dans ma question initiale par «devant», je n'impliquais pas que «WHERE» devrait être immédiatement devant une expression «[]». Désolé si ce n'était pas clair.


Une partie du code que vous souhaitez supprimer dans ce cas n'est pas entre crochets. Est-ce que c'est exprès?


Oui. Plus généralement, si une clause «WHERE» contient au moins une expression entre crochets, je souhaite supprimer la clause «WHERE» complète. Dans mon cas, la clause 'WHERE' est limitée par 'GROUP', 'ORDER' ou la fin de la chaîne. C'est ce que je vise.


Alors ... pour m'assurer que je fais les choses correctement. La partie que vous souhaitez supprimer (1) commence par un «où»; (2) contient du texte entre crochets. (3) se termine par group by / order by / the end of the string. Correct? Et une question - que se passe-t-il si vous avez «grouper par» entre parenthèses?


Oui c'est correct. 'group by' ne peut pas être entre crochets car '[]' ne peut contenir qu'un filtre qui sera à l'intérieur d'une clause where. Un autre exemple: un code où field1 = 'bonjour' et [created_at :: DATE = daterange] groupent par 1 un peu plus de code devient un groupe de codes par 1 un peu plus de code


Je pense que je viens de trouver un contre-exemple pour quand cette expression régulière ne fonctionne pas comme prévu: "" où [Include_Fakes | TRUE] group par 1 ordre par 1,3) où signed_up_date> = dateadd ('[aggregation]', - [Last_N_Periods | 12], CURRENT_DATE) "" "devrait finir avec group par 1 ordre de 1,3" mais il produit une chaîne vide - il semble donc que la double apparence de "where ... []" cause un problème


Regarde ça. Cela signifie que vous pouvez avoir plusieurs instances de where suivies de crochets, chacune se terminant par groupe / ordre / fin d'expression. Droit?


Je crois que votre dernière version ne fonctionne que si la deuxième occurrence de "where [condition]" est suivie de l'expression de fin de chaîne. Si vous ajoutez simplement «group by» à la fin du dernier «txt», il renvoie «group by» au lieu de «group by 1 order by 1,3) group by», donc l'expression rationnelle saute fondamentalement la clause interne. À ce stade, je ne suis pas vraiment sûr de comprendre comment résoudre ce problème ...


similaire se produit dans ce cas: real_code = "" "WHERE texte où [agrégation] grouper par 1 ordre par 1 desc" "" print (re.sub (exp, r "", real_code, flags = re.S | re.I )) >> grouper par 1 ordre par 1 desc


Hmm. Je vais l'examiner.


Quant au dernier, il semble aller bien. Il y a DEUX expressions où. L'un avec des crochets, qui est supprimé, et l'autre sans - et celui-ci y reste.


tu as raison. Mais le regex a supprimé LES DEUX «où» alors qu'il ne devrait toucher que celui qui est suivi de [agrégation], n'est-ce pas? donc "où le texte où [agrégation] grouper par 1 ordre par 1 desc" devient "où le texte grouper par 1 ordre par 1 desc"


avez-vous eu l'occasion de l'examiner? Je suis un peu coincé pourquoi il ne supprime pas les occurrences conséquentes de 'where [filter]' ...


C'est la sortie que je vois: «où le texte est groupé par 1 ordre par 1 desc». Qu'est ce qui ne va pas avec ça?


Désolé, je faisais référence à mon premier commentaire d'hier: txt = "" "où [condition1] group par 1) où [condition2] group by 2" "" renvoie group by 2 au lieu de "group by 1) group by 2" , donc il "avale" la partie intérieure



3
votes

Vous pouvez utiliser des lookaheads négatifs pour trouver la dernière correspondance possible:

>>> import re
>>> re.sub(r"where((?!where).)*?]\s?", "", "where that and that do that where [this = 1] group by 1,2,3")
'where that and that do that group by 1,2,3'
>>> re.sub(r"where((?!where).)*?]\s?", "", "where this condition and [this = 1] group by 1,2,3")
'group by 1,2,3'

Démo


2 commentaires

cela ne fonctionnerait pas si j'avais plusieurs [] , c'est-à-dire re.sub (r "where ((?! where).) *?] \ s?", "", " où cette condition et [this = 1] et [that = 1] group by 1,2,3 ") ne produit pas le résultat souhaité


Si vous voulez faire correspondre avidement jusqu'au dernier ] , changez simplement le *? en un * .



1
votes

Vous pouvez faire correspondre la dernière occurrence de where en utilisant un jeton gourmand tempéré , puis correspond à n'importe quel caractère sauf [ ou ] .

Ensuite, répétez la correspondance d'une ouverture à la fermeture [ ] et répétez cette correspondance plus d'une fois.

group by 1,2,3
where that and that do that group by 1,2,3
  • \ bwhere Limite de mot et correspondance où
  • (?: Groupe sans capture
    • (?: Groupe sans capture
      • (?! où) [^] [] Correspond à n'importe quel caractère sauf [ ou ] si à droite n'est pas
    • ) * Fermer le groupe et répéter plus de 0 fois
    • \ [[^] [] *] Correspond à 0 fois ou plus n'importe quel caractère sauf [ ou
  • ) + Fermer le groupe et répéter 1+ fois pour correspondre au moins une fois [...
  • \ s * Correspond à 0+ caractères d'espacement

Démo Regex | Démo Python

Exemple de code

import re
 
regex = r"\bwhere(?:(?:(?!where)[^][])*\[[^][]*])+\s*"
txt = ("where this condition and [this = 1] group by 1,2,3\n"
    "where that and that do that where [this = 1] and [that = 1] group by 1,2,3")
result = re.sub(regex, "", txt)
 
print (result)

Sortie

\bwhere(?:(?:(?!where)[^][])*\[[^][]*])+\s*


0 commentaires