regex Kommentare aus Text entfernen

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
hans
User
Beiträge: 728
Registriert: Sonntag 22. September 2002, 08:32
Wohnort: Sauerland
Kontaktdaten:

Und ich dachte, ich beherrsche die :(

Ich möchte aus einer SQL-Anweisung, welche als String vorliegt, die SQL Kommentare entfernen. Ei SQL Kommentar beginnt mit /* und endet mit */. Der Kommentar kann sich über mehrere Zeilen erstrecken, Zeilenumbrüche habe ich aber schon entfernt.

im vim funktioniert dieses Suchmuster

Code: Alles auswählen

1,$s/\/\*.*\*\///g
Der Versuch in Python funktioniert scheinbar so nicht. Die Aufgabe: Entferne den Text zwischen /* und */ eiischließlich der Kommentarzeichen

Code: Alles auswählen

>>> import re
>>> statement = '/*Kommentar*/select * from xyz;/*Noch mehr Kommentar*/'
>>> comStatement=re.compile(statement)
>>> re.escape('/*')
'\\/\\*'
>>> re.escape('*/')
'\\*\\/'
>>> comStatement.sub('\s\\/\\*.*\\*\\/\s', '', re.IGNORECASE)
''
>>
Noch eine Frage zu sub(): In der Doku ist re.sub() als deprciated gekennzeichnet und wird es in der 3.6er Version nicht mehr geben. Gilt das auch für dir regex.sub()?
BlackJack

@hans: Lies die Dokumentation noch mal genauer. Nicht die Funktion verschwindet, sondern das Verhalten was da beschrieben wird löst bei 3.5 eine Warnung aus und ist bei 3.6 dann verboten → Ausnahme.
BlackJack

@hans: Bezüglich Deines regulären Ausdrucks: Der beginnt und endet mit '\s', aber bei keinem der beiden Kommentare steht davor und danach ein „whitespace“-Zeichen. Das kann dann ja schon mal nicht passen. Und reguläre Ausdrücke sind in der Regel ”greedy”, das heisst das '.*' würde wenn der Rest stimmt alle Zeichen zwischen dem allerersten '/*' und dem letzten '*/' matchen, also auch den SQL-Teil dazwischen.
BlackJack

@hans: Ich sehe jetzt erst das Du die SQL-Anweisung als regulären Ausdruck kompilierst. Wie kommt man denn auf *die* Idee?

Hier ist die/eine (nicht robuste) Lösung: https://regex101.com/r/eS6bD5/1

Die Webseite eignet sich auch zum Testen/Entwickeln von regulären Ausdrücken ganz gut.
hans
User
Beiträge: 728
Registriert: Sonntag 22. September 2002, 08:32
Wohnort: Sauerland
Kontaktdaten:

Ich bekomme da nur einen leeren String zurück

Code: Alles auswählen

>>> comStatement.sub('\/\*.*?\*\/', '', re.IGNORECASE)
''
>>> comStatement
re.compile('/*Kommentar*/select * from xyz;/*Noch mehr Kommentar*/')
>>> 
'/s' jupp, lesen nicht raten! Macht der Gewohnheit. Steht im vim für substitute.

Keine Bange, werde den compilierten String nicht auf die Datenbank loslassen :) Hintergrund ist, das ich wissen muss um welche Art der Anweisung es sich handelt (Select, Modify, Create, Drop). Wenn ich allen Müll entferne, dann müsste das erste Wort Auskunft darüber geben ('WITH lasse ich jetzt einmal aussen vor, Ist mir (noch) unbekannt)

Danke für den Link.
Sirius3
User
Beiträge: 17750
Registriert: Sonntag 21. Oktober 2012, 17:20

@hans: Programmieren durch raten hat auch schon im anderen Thread von Dir sehr weit geführt. Du vertauschst den regulären Ausdruck mit dem zu durchsuchenden Text. So wird das nichts.

Warum mußt Du überhaupt wissen, um was für ein SQL-Statement es sich handelt? Da Du das in den Quelltext schreibst, weißt Du das ja auch.
hans
User
Beiträge: 728
Registriert: Sonntag 22. September 2002, 08:32
Wohnort: Sauerland
Kontaktdaten:

@sirius3: aua, manchmal sieht man den Wald vor lauter Bäumen nicht mehr. Vorher schon mal richtig angewendet.

Ich weiss schon welche SQL Abfragen ich im Code verwende, aber ich schreibe an einem Editor. SQL eintippen und ausführen. Nur SELECT führt zu einer Datenausgabe. Mal sehen, vielleicht baue ich das Programm noch so um, dass ohne Aufrufparameter nur SELECT zulässig ist.
BlackJack

@hans: Aber ein SELECT muss nicht zwingend am Anfang stehen. Man kann ja mehr als eine SQL-Anweisung durch Semikolons getrennt angeben. Ich würde am Ende einfach schauen welche Datensätze nach dem `execute()` zur Verfügung stehen und die Anzeigen. Auch dann wird ja nur etwas angezeigt wenn die SQL-Anweisung(en) auch tatsächlich zu Ergebnisse geführt haben. Und nicht nur SELECT führt zu Ergebnissen. PRAGMAs können beispielsweise auch Ergebnisse liefern.
hans
User
Beiträge: 728
Registriert: Sonntag 22. September 2002, 08:32
Wohnort: Sauerland
Kontaktdaten:

@BlackJack: Ich weiss, dass das geht. Mehrere Select-Statements in einem Script macht m.E. kein Sinn, es sei denn nur das letzte Statement liefert ein Ergebnis. Aber für solche scripts geht auch nicht ....cursor().execute() sondern ....cursor.executemany()

Ich hatte es in meinem letzten Post schon angedeutet, da gibt es noch eine WITH Clause. Die steht laut Handbuch auch ganz vorne. Habe aber noch nicht herausbekommen wofür die gut ist. Ich bin die letzten 30 Jahre ohne die ausgekommen, also hoffe ich dass die nicht wichtig ist, sonst muss ich doch noch einmal in die Tasten greifen. Meine Scripte scheinen jetzt sicher erkannt zu werden.

Dann wollen wir mal sehen, was SQLite macht wenn ich mit 'SELECT ......FROM (SELECT ...............) ....... komme. Aber das ist dann nicht mehr Python.
BlackJack

@hans: Nö, `executemany()` ist für etwas anderes als mehrere unterschiedliche SQL-Anweisungen auszuführen. Das ist dafür da um eine SQL-Anweisungen mit mehr als einem Satz Daten auszuführen.

Eine SQL-Anweisung kann auch mit EXPLAIN anfangen.

Ich verstehe immer noch nicht warum Du Dich da überhaupt mit einer am Ende wahrscheinlich wenig robusten Heuristik mit regulärem Ausdruck abgibst, wenn Du doch einfach überprüfen kannst ob es Datensätze gibt, die angezeigt werden können. Einfach `description` vom Cursor-Objekt nach der Ausführung der SQL-Anweisung anschauen und dann weiss man ob es potentiell Ergebnisse gibt oder nicht.
hans
User
Beiträge: 728
Registriert: Sonntag 22. September 2002, 08:32
Wohnort: Sauerland
Kontaktdaten:

Hmm, da wird der Hund in der Pfanne verrückt :oops: Schau mal was da zum Vorschein kommt.

Code: Alles auswählen

sqlite> explain select * from sqlite_master;
addr  opcode         p1    p2    p3    p4             p5  comment      
----  -------------  ----  ----  ----  -------------  --  -------------
0     Init           0     12    0                    00  Start at 12  
1     OpenRead       0     1     0     5              00  root=1 iDb=0; sqlite_master
2     Rewind         0     10    0                    00               
3       Column         0     0     1                    00  r[1]=sqlite_master.type
4       Column         0     1     2                    00  r[2]=sqlite_master.name
5       Column         0     2     3                    00  r[3]=sqlite_master.tbl_name
6       Column         0     3     4                    00  r[4]=sqlite_master.rootpage
7       Column         0     4     5                    00  r[5]=sqlite_master.sql
8       ResultRow      1     5     0                    00  output=r[1..5]
9     Next           0     3     0                    01               
10    Close          0     0     0                    00               
11    Halt           0     0     0                    00               
12    Transaction    0     0     43    0              01  usesStmtJournal=0
13    TableLock      0     1     0     sqlite_master  00  iDb=0 root=1 write=0
14    Goto           0     1     0                    00               
sqlite> explain query plan select * from sqlite_master;
0|0|0|SCAN TABLE sqlite_master
So, und jetzt werde ich nochmals die Doku wälzen, denn Rewind, Next und GoTo wecken meine Neugier.

Mit SQLite habe ich bisher nicht gearbeitet. Meine Kenntnisse stammen in der Hauptsache von Firebird. Da habe ich das Problem nicht. Ich definiere dort in der Datenbank einige Datenbankuser und verteile die Rechte da. Der User Heinbloed hatte das Passwort Bordratte und durfte alles sehen, mehr nicht :D Ich möchte nicht, dass da jemand ein "DROP TABLE Dingenskirchen;" ausführt.
BlackJack

@hans: Benutzer und Zugriffsschutz gibt es bei SQLite nicht. Wenn man so etwas braucht, dann ist eine eingebettete Datenbank vielleicht auch nicht das was man haben will. Insbesondere weil es sich um einfache Dateien handelt die auch zur Weitergabe geeignet und gedacht sind. Das ist als würde man in einem Tabellenkalkulationsdokument verschiedene Benutzer und verschiedene Rechte haben wollen.
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

hans hat geschrieben:So, und jetzt werde ich nochmals die Doku wälzen, denn Rewind, Next und GoTo wecken meine Neugier.
SQLite kompiliert Querys zu Bytecode - das ist was du siehst - der von einer VM ausgeführt wird.
Antworten