Laden...

RegExp auf NICHT matchen

Erstellt von Cpt_Future vor 18 Jahren Letzter Beitrag vor 18 Jahren 4.493 Views
C
Cpt_Future Themenstarter:in
97 Beiträge seit 2005
vor 18 Jahren
RegExp auf NICHT matchen

Hallo,

(am besten gleich zu DIE PROBLEMATIK springen)

ich bin gerade dabei mit ANT ein build zu schreiben, dass u.a. in einer C++ (.cpp) Datei ein '#define VERSION "1.2.3"' neu setzt, per RegExp.

Per ANT ist das Inkrementieren on-the-fly wohl nicht möglich, daher muss ich den Umweg gehen, die Versionsnummer zu extrahieren, als Property (~Variable) zu integrieren und neu zu schreiben.
Das Integrieren ist per Datei im Format "key = value" (INI-Style) möglich. Also dachte ich, formatiere ich die zu suchende Zeile so um und lösche den restlichen Quellcode raus.

Die Zeile die ich treffen möchte:
#define VERSION "1.2.34"

Mein Ziel:
#define VERSION "1.2.35"

Ich matche die Zeile so:
#define VERSION "([0-9]+).([0-9]+).([0-9]+)"

(ANT liest die builds per XML ein, daher &quot😉

Wie finde ich alle Zeilen, die NICHT so aufgebaut sind und lösche sie?

Meine Idee war, anstatt nochmal nach nicht genau dieser Zeile zu suchen

Pseudocode! (der übrigens nicht funktioniert)
!(#define VERSION "([0-9]+).([0-9]+).([0-9]+)")

setze ich vor meine Trefferzeile einen String, der einmalig im Quelltext ist, z.B. ANT_BUILD_UNIQUEFLAG und suche im 2. Durchgang jetzt nach jeder Zeile, die NICHT mit "ANT_BUILD_UNIQUEFLAG" anfängt und ersetze sie durch einen Leerstring.

Somit wäre mein Ergebnis
ANT_BUILD_UNIQUEFLAG#define VERSION "1.2.34"

DIE PROBLEMATIK:

Ich finde einfach den regulären Ausdruck nicht, für ein Matching auf alle Zeilen, die nicht mitdem String "ANT_BUILD_UNIQUEFLAG" anfangen.

Meine Ideen
!(ANT_BUILD_UNIQUEFLAG).*
[(ANT_BUILD_UNIQUEFLAG)].*

Ersteres geht mit
http://www.regular-expressions.info/javascriptexample.html
wunderbar, in Java aber eben nicht mehr.
Zweiteres ist tricky, funktioniert zwar, trifft aber auch NNNNTABU_ILD_UNIQUEFLAG.

Der Regexp "[PETER]" trifft ja nicht nur den String "PETER" sondern eben auch "TEERP", das will ich ja aber verhindern.

Puh, hat jemand verstanden was ich meine. Rätsel da schon die ganze Zeit mit nem Kollegen rum.

Und wenn jemandem ne leichtere Lösung des Problems zu ANT einfällt, einfach sagen 🙂 🙂 Ein kleines Programm schreiben, dass ich per ANT anstosse will ich aber nicht.

Etwas nicht tun zu können, ist kein Grund etwas nicht zu tun.
-Alf

49.485 Beiträge seit 2005
vor 18 Jahren

Hallo Cpt_Future,

ich habe den Beitrag nur überflogen. Frag nach, wenn du es anderes meintest.

Wenn man alle Zeilen haben will, die nicht auf ein Muster passen, benutzt man einfach die Negation von IsMatch oder den else-Teil des if.


if (!RegEx.IsMatch (...)) {
}

//oder 

if (RegEx.IsMatch (...)) {
} else {
  // hier
}

herbivore

_
416 Beiträge seit 2005
vor 18 Jahren

Hallo,

also matchen scheint mit folgendem RegEx zu funktionieren:
^(?!#define VERSION "(\d+).(\d+).(\d+)").*

Damit sollte also auch löschen funktionieren.

cu, tb

49.485 Beiträge seit 2005
vor 18 Jahren

Hallo Cpt_Future,

Der Regexp "[PETER]" trifft ja nicht nur den String "PETER" sondern eben auch "TEERP", das will ich ja aber verhindern.

Der Regex "[PETER]" trifft auf einen der Buchstaben P, E, T, oder R. Wenn du auf PETER matchen willst, musst du genau das schreiben: "PETER".

herbivore

C
Cpt_Future Themenstarter:in
97 Beiträge seit 2005
vor 18 Jahren

Original von tb
also matchen scheint mit folgendem RegEx zu funktionieren:
^(?!#define VERSION "(\d+).(\d+).(\d+)").*

Vielen Dank, das war die Lösung, puh endlich 🙂
Danke auch an herbivore, C# kann ich aber leider nicht einsetzen 🙂

Etwas nicht tun zu können, ist kein Grund etwas nicht zu tun.
-Alf

49.485 Beiträge seit 2005
vor 18 Jahren

Hallo Cpt_Future,

würde mich mal interessieren, warum du meinst, es nicht einsetzen zu können.

Wenn du dagegen nur meinst, dass du die eine Lösung nimmst und die andere nicht, ist das voll ok. Aber ich verstehe nicht, warum meine Lösung nicht einsetzbar sein soll.

herbivore

C
Cpt_Future Themenstarter:in
97 Beiträge seit 2005
vor 18 Jahren

Es geht darum per Ant einen XML-Build zu starten. Übergeordnetes Ziel ist es, das Build laufen zu lassen, nachzuschauen ob auf dem CVS-Server eine ältere Version von "bla.cpp" liegt als auf dem Client

Wenn ja:
"bla.h" öffnen, die Zeile "#define VERSION 1.2.3" suchen (per RegExp), die Subsubversion hochzählen und "bla.cpp" und "bla.h" zu commiten (Server-Version updaten)

Wenn nein:
keine Änderung, fertig.

Da es möglich sein soll, das Build von jedem beliebigen Rechner starten zu können (Linux, Windows), wollte ich kein externes Programm verwenden (schon garnich C#), dass mir die Subversion hochzählt. Ich wollte es mit Ant lösen und habs jetzt auch geschafft.

Wen's interessiert:


<?xml version="1.0" encoding="UTF-8"?>
<project name="Build Increment" default="increment">
	<property file="increment.properties"/>
	
	<target name="increment" description="Increments the subversion" >
		<!-- first copy is to transform source.cpp to an temporary ant properties file -->
		<copy file="${increment.source}" tofile="${tempfolder}/${increment.tempfile1}"/>
		
		<!-- second copy is to replace the version -->
		<copy file="${increment.source}" tofile="${tempfolder}/${increment.tempfile2}"/>
		
		<!-- replace all irrelevant lines in tempfile1 (source.cpp) -->
		<replaceregexp file="${tempfolder}/${increment.tempfile1}" byline="true"
			match="^\s*(?!#define VERSION &quot;(\d+)\.(\d+)\.(\d+)&quot;)(.*)"
			replace=""/>
		
		<!-- replace the relevant line by a property command -->
		<replaceregexp file="${tempfolder}/${increment.tempfile1}" byline="true"
			match="^#define VERSION &quot;(\d+)\.(\d+)\.(\d+)&quot;"
			replace="increment.oldsubversion = \3"/>
		
		<!-- include the new property -->
		<property file="${tempfolder}/${increment.tempfile1}"/>
		
		<!-- increment the property/subversion -->
		<propertyfile file="${tempfolder}/${increment.tempfile1}">
			<entry key="increment.oldsubversion" type="int" operation="+" value="1" default="0"/>
		</propertyfile>
		
		<!-- replace the name of the property, obviously - it's not possible to replace a property -->
		<replace file="${tempfolder}/${increment.tempfile1}" token="increment.oldsubversion" value="increment.newsubversion"/>
		
		<!-- include the new property (name) -->
		<property file="${tempfolder}/${increment.tempfile1}"/>
		
		<!-- replace the source definition by the incremented subversion -->
		<replaceregexp file="${tempfolder}/${increment.tempfile2}" byline="true"
			match="^#define VERSION &quot;(\d+)\.(\d+)\.\d+&quot;"
			replace="#define VERSION &quot;\1.\2\.${increment.newsubversion}&quot;"/>
		
		<!-- overwrite the original source file by the edited version -->
		<copy file="${tempfolder}/${increment.tempfile2}" tofile="${increment.source}" overwrite="true"/>
		
		<!-- print the information -->
		<echo message="incrementing from ${increment.oldsubversion} to ${increment.newsubversion}"/>
	</target>
</project>

Klappt wunderbar, gibt sicher noch ne bessere Lösung, aber das es funktioniert und Builds ja meistens eh automatisiert über Nacht laufen ist das schon wunderbar!

Etwas nicht tun zu können, ist kein Grund etwas nicht zu tun.
-Alf