staging.inyokaproject.org

regex in geany

Status: Gelöst | Ubuntu-Version: Ubuntu GNOME 23.04 (Lunar Lobster)
Antworten |

nitja

Anmeldungsdatum:
14. Februar 2018

Beiträge: 115

Ich kämpfe nun schon ein paar Tage mit den "Regulären Ausdrücken" für geanys "Ersetzen"-Dialog.

Nachdem ich ein paar Stunden gebraucht habe um wieder auf den Stand zu kommen, den ich mir vor ein paar Jahren schon mal erkämpft hatte, stehe ich nun vor einer echten Hürde:

Ich suche in strings mit Zahlen, deren Dezimalstellen auf mindestens 3 9ern enden, die letzte von 9 verschiedene Ziffer, möchte die durch eine um 1 erhöhte Ziffer ersetzen und die abschließenden 9er löschen.

Die Suche findet auch die richtige Stelle und besagte letzte von 9 verschiedene Ziffer, aber die Ersetzung krieg ich einfach nicht hin.

Beispiel:

Text ist x="2.8499999", Such-string ist (.\d+?)(0|1|2|3|4|5|6|7|8)9{3}9+?" und die (nur testweise) Ersetzung \1\2" liefert x="2.84".

Nun soll da nicht \2, also 4 stehen, sondern 5 also x="2.85"

Das sollte eigentlich (u.a.) mit "conditional subpatterns", die geanys "Reguläre Ausdrücke" in "pearl-flavor" anbieten, möglich sein.

Statt des gewünschten Ergebnisses bewirken meine Versuche nur noch "Karussell im Kopf". (← sehr unangenehm, das)

Falls hier also eine Person mit liest, die mir da auf die Sprünge helfen kann und will, soll ihr der allerherzlichste Dank gewiss sein.

noisefloor Team-Icon

Ehemaliger
Avatar von noisefloor

Anmeldungsdatum:
6. Juni 2006

Beiträge: 28316

Hallo,

spontan würde ich sagen: geht nicht, weil du ja irgendwie irgendwann +1 rechnen muss. Und rechnen geht nicht, soweit ich weiß.

Was du am Ende willst, zumindest verstehe ich das Beispiel so, ist auf 2 Nachkommastellen runden, oder? Was soll mit einer einem String wie "2.499999" werden - 2.49 oder 2.50?

Gruß, noisefloor

nitja

(Themenstarter)

Anmeldungsdatum:
14. Februar 2018

Beiträge: 115

noisefloor schrieb:

… irgendwie irgendwann +1 rechnen muss. Und rechnen geht nicht, soweit ich weiß.

… ist [in dem Beispiel] auf 2 Nachkommastellen runden, oder? Was soll mit einer einem String wie "2.499999" werden - 2.49 oder 2.5

Dank Dir für die schnelle Reaktion! Und ja, beides zutreffend. (außer, dass man dafür nicht "rechnen" muss)

Statt Rechnen möchte ich die Ersetzung von einer Bedingung abhängig machen:

Wenn \1 (die letzte von 9 verschiedene Dezimale) "0" ist, dann hänge stattdessen "1" an, wenn sie "1" ist "2", u.s.w. bis "8" …

Alternativ könnte ein Listenvergleich(?) wie für ein "dictionary" funktionieren, aber das im Detail zu verstehen, hab ich vorerst aufgegeben.

Wenn ich das geschafft habe, kann ich mich auch um den Fall "9" kümmern (muss wohl rekursiv werden).

noisefloor Team-Icon

Ehemaliger
Avatar von noisefloor

Anmeldungsdatum:
6. Juni 2006

Beiträge: 28316

Hallo,

Statt Rechnen möchte ich die Ersetzung von einer Bedingung abhängig machen:

Ja ok, aber dann brauchst du ja ein Mapping, was wie ersetzt werden soll, also 2 statt 1, 3 statt 2. Ich glaube (weiß es aber nicht definitiv), dass das mit RegEx alleine nicht geht.

Gruß, noisefloor

nitja

(Themenstarter)

Anmeldungsdatum:
14. Februar 2018

Beiträge: 115

noisefloor schrieb:

… ein Mapping, was wie ersetzt werden soll, also 2 statt 1, 3 statt 2. Ich glaube (weiß es aber nicht definitiv), dass das mit RegEx alleine nicht geht.

Doch, geht. Habe etliche Beispiele gesehen (die meisten bei stackoverflow). Die werden zwar "erklärt", aber ich hab's nicht ausreichend verstanden.

Eine erste Hürde war, dass die sich ausschließlich auf M$s Windoof und da fast ausschließlich auf Notepad++ beziehen. Und es dauerte eine Weile, bis ich kapiert hab, dass ich Notepads Python-Regex in geanys Perl-Regex "übersetzen" muss. Wenn man's richtig macht kann geanys Regex mindestens genauso viel wie - wahrscheinlich mehr als - die von Notepad++.

Aber auch die Erkenntnis hat mir nicht die Lösung gebracht. Dafür ist mein Verständnis von Regex wohl doch zu lückenhaft.

noisefloor Team-Icon

Ehemaliger
Avatar von noisefloor

Anmeldungsdatum:
6. Juni 2006

Beiträge: 28316

Hallo,

dass die sich ausschließlich auf M$s Windoof

Was ist Windoof? Ist das irgendwie für den Problem relevant? Wenn ja, bitte erklären.

Unabhängig davon: es gibt verschiedene RegEx Implementierung, die unterschiedlich "weit" / tief gehen. Das ist oft, zumindest bei Standardproblemen, egal, bei dem was du vorhast könnte das schon in Regionen vorstoßen, wo es nicht egal ist. Von daher ist es dann auch wichtig zu wissen, welche Implementierung Programm $FOO benutzt. Hast du für Geany ja schon recherchiert. Sonst kann man an den Punkt kommen, wo man denkt, die RegEx wäre falsch - aber in Wirklichkeit unterstützt nur die RegEX Engine von Programm $FOO diese RegEx Syntax nicht.

BTW: ich benutze, wenn ich mal mit RegEx was machen muss, die Seite https://regex101.com/ gerne zum rumspielen.

Welche RegEx hast du den für die X+1 Substitution benutzt bzw. versucht? Es hilft immer, ein Beispiel zu haben. Auch wenn dieses ggf. nicht funktioniert.

Gruß, noisefloor

shiro

Anmeldungsdatum:
20. Juli 2020

Beiträge: 611

nitja schrieb:

... dass ich Notepads Python-Regex in geanys Perl-Regex "übersetzen" muss.

Oops. Jetzt bin ich etwas verwirrt. Notepad++ vor Version 6.0 nutzte den Posix Flavor von Regex. Ab V6.0 nutzt es den Perl Flavor (PCRE), erkennbar an $1 bzw \1 als Backreferenz. Ein Python Flavor ist mir hier nicht bekannt.

Notepad++ und Geany nutzen wie SciTE als Core das Scintilla Paket. Dann werden die Übereinstimmungen aber geringer. Wie noisefloor schon schrieb, kannst du mit RegEx nicht rechnen. Hierzu benötigst du ein Compute-Element, das bei Notepad++ und Geamy über Plugins implementiert wird. Bei SciTE kannst du den LUA Interpreter leicht nutzen.

An deiner Stelle würde ich wegen Scintilla von Notepad++ (wine) oder Geany auf SciTE wechseln. SciTE ist sicher für Anfänger ein dickeres Brett als Geany aber für etwas komplexere Nutzung wegen LUA die leistungsfähigere Lösung.

nitja

(Themenstarter)

Anmeldungsdatum:
14. Februar 2018

Beiträge: 115

shiro schrieb:

… Notepad++ vor Version 6.0 nutzte den Posix Flavor von Regex. Ab V6.0 nutzt es den Perl Flavor (PCRE), erkennbar an $1 bzw \1 als Backreferenz. Ein Python Flavor ist mir hier nicht bekannt.

oha! Dann waren die Beispiele, die mir ein anderes Flavor nahelegten ( {1} statt \1 als back-reference ), wohl alle von älteren Notepad++-Versionen. Wo ich das vermeintliche Python-Flavor "gefunden" hatte, müsste ich erst noch mal nachschauen. Lohnt aber vermutlich nicht wirklich.

PCRE ist was ich für Geany gefunden habe: https://www.geany.org/manual/gtk/glib/glib-regex-syntax.html

shiro schrieb:

Notepad++ und Geany nutzen wie SciTE als Core das Scintilla Paket. Dann werden die Übereinstimmungen aber geringer. Wie noisefloor schon schrieb, kannst du mit RegEx nicht rechnen. Hierzu benötigst du ein Compute-Element, das bei Notepad++ und Geamy über Plugins implementiert wird. Bei SciTE kannst du den LUA Interpreter leicht nutzen.

Wie gesagt, ich meine ja nicht wirklich rechnen damit rechnen zu können (weil mir klar ist, dass das mir Regex alleine nicht geht),

nur das replacement abhängig vom gefundenen Zeichen auswählen.

Und dafür habe ich viele Beispiele gefunden (aber nicht genügend verstanden).

SciTE ist sicher für Anfänger ein dickeres Brett als Geany aber für etwas komplexere Nutzung wegen LUA die leistungsfähigere Lösung.

… uns das, wo mich diesbezüglich schon die Dicke des Geany-"Bretts" z.Z. zu überfordern scheint …

nitja

(Themenstarter)

Anmeldungsdatum:
14. Februar 2018

Beiträge: 115

noisefloor schrieb:

Welche RegEx hast du den für die X+1 Substitution benutzt bzw. versucht? Es hilft immer, ein Beispiel zu haben. Auch wenn dieses ggf. nicht funktioniert.

Muss ich nachreichen, am besten dann zusammen mit dem funktionierenden Beispiel, das mir den jeweiligen Versuch nahelegte - wird aber vermutlich bis morgen dauern.

Jedenfalls allen Beteiligten ganz herzlichen Dank für das Engagement!

nitja

(Themenstarter)

Anmeldungsdatum:
14. Februar 2018

Beiträge: 115

Hier ein Beispiel, in dem das "Conditional Replacement" wohl funktioniert: https://regex101.com/r/We97pa/2

Ich hatte auch einfachere gesehen und versucht für meine Aufgabe nach zu bauen, aber noch nicht wieder gefunden. Und auch nicht erfolgreich nach gebaut.

noisefloor Team-Icon

Ehemaliger
Avatar von noisefloor

Anmeldungsdatum:
6. Juni 2006

Beiträge: 28316

Hallo,

habe gestern mal nachgelesen: ja, es gibt RegEx Implementierungen, die Mappings können, also sowas wie "mache 1 zur 2, 2 zur 3 usw". Hatte ich bis dato noch nicht gesehen und die Syntax habe ich auch nicht wirklich verstanden. Wenn man dann noch Mappings auf Capture Groups anwendet wird's sicherlich nicht einfacher. Aber ich _glaube_, dass das schon gehen würde.

Gruß, noisefloor

nitja

(Themenstarter)

Anmeldungsdatum:
14. Februar 2018

Beiträge: 115

Auf regex101 hab ich's jetzt geschafft: (Danke für den Hinweis - hat freilich gedauert, bis ich die Ersetzung eingeben konnte: anderes Beispiel zum Editieren missbraucht)

test (der Text zwischen den Zahlen ist belanglos, soll aber erhalten bleiben):

abc 2.499999 mno<44> 3.459999 tzu 1.999999 0.0499999

Dictionary:0=1:1=2:2=3:3=4:4=5:5=6:6=7:7=8:8=9

suche: (\d)[.]?9{3,}9(?=.*:\1=(\d))

ersetze: \2

ergibt:

abc 2.5 mno<44> 3.46 tzu 2 0.05

Dictionary:0=1:1=2:2=3:3=4:4=5:5=6:6=7:7=8:8=9

Bleibt zu hoffen, dass Geany das auch versteht.

nitja

(Themenstarter)

Anmeldungsdatum:
14. Februar 2018

Beiträge: 115

nitja schrieb:

Bleibt zu hoffen, dass Geany das auch versteht.

Wäre ja auch (zu|) einfach (|zu schön) gewesen.

Und weil's Geany nicht rafft, hatte ich den "gelöst"- nicht gesetzt.

Auf Geany hatte ich mich verlassen, weil mir(?) in der [url=https://www.geany.org/manual/gtk/glib/glib-regex-syntax.html]Doku zu Geanys PCRE-Unterstützung[/url] (letzter Absatz bei "Copyright") keine Einschränkungen erkennbar sind.

Von Geany mag ich trotzdem nicht weg, weil ich da schon einige Scripte habe, die ich für die (60-150) Dateien, für die sich die spezielle RegEx-Frage stellte, brauche und mit denen ich nicht in eine neue Umgebung umziehen mag/kann.

Das Positive daran ist, dass es eben an Geany lag und der Verlust an kognitiven Fähigkeiten doch geringer scheint als bei dem Anlass befürchtet.

Die Drumherumarbeit, die jetzt auch den "gelöst--Status" beschert:

Ein Perl-Script, das ich (automatisch) von Geany aus anstoßen kann.

… und hier das Prinzip (ohne die allfälligen Dateioperationen):

1
2
3
4
5
6
$TextRoh = " abc 2.499999 mno<44> \n\n 3.459999 tzu 1.999999 \n blah blah \n\n 0.0499999 \n\n";
print "Text vor den Ersetzungen:\n" . $TextRoh;
$TextNeu = $TextRoh . "\n:0=1:1=2:2=3:3=4:4=5:5=6:6=7:7=8:8=9\n";
$TextNeu =~ s/(\d)[.]?9{3,}9(?=.*:\1=(\d))/$2/gsx;
$TextNeu =~ s/:0=1:1=2:2=3:3=4:4=5:5=6:6=7:7=8:8=9\n//sx;
print "… und danach:\n" . $TextNeu;

Ganz herzlichen Dank noch mal, vor allem an "noisefloor" 😎 für die Anregungen, ohne die ein noch längerer K(r)ampf, oder Verzweiflung bis zum Aufgeben wahrscheinlicher gewesen wäre.

😠 - Wie kann man hier Links wie in der 3. Zeile unter dem Zitat sauber einstellen?

noisefloor Team-Icon

Ehemaliger
Avatar von noisefloor

Anmeldungsdatum:
6. Juni 2006

Beiträge: 28316

Hallo,

gern geschehen und schön, dass es am Ende doch funktioniert hat 👍

Die Doku hatte ich auch die Tage gefunden. Geany benutzt also die RegEx Implementierung aus GLib. Die ist lt. Doku auch PCRE-kompatibel, aber hat anscheinend nicht die Ersetzung via Dictionary implementiert. Das nehme ich übrigens von dem Thread hier mit, dass es sowas bei RegEx, je nach Implementierung, auch geben kann.

Gruß, noisefloor

Antworten |