Seite 1 von 2

QString::replace( )?

Verfasst: 4. Juni 2007 13:49
von Whitefurrows
Hallo,

wie kann ich in einem String zwei Zeichen ersetzen? Die Strings sehen z.B. so aus:

"<123> Text" oder "Text <123> Text"

Jetzt möchte ich "<" durch "(" und ">" durch ")" ersetzen.

Um unnötige Deklarationen zu vermeiden habe ich mir das in etwa so vorgestellt:

Code: Alles auswählen

ui.label->setText( label->text().replace(QRegExp(???)) );
Hat jemand eine Idee wie das funktionieren kann?

Gruß,

Whitefurrows

Verfasst: 4. Juni 2007 14:58
von macman
Ja, aber momentan keine Zeit das zu prüfen und bevor ich Müll schreibe, lass ich es lieber. Wenn Du es mit RegExp machen willst, dann studiere mal http://www.regular-expressions.info/. Danach solltest Du es alleine hin bekommen. Vergiss jedenfalls nicht die Gier abzuschalten :-)
setMinimum(...) ist das, IIRC. Ein weiteres Stichwort in der Qt-Doku wäre cap(int n).

Verfasst: 4. Juni 2007 16:42
von Whitefurrows
Hallo,

in der Doku habe ich gesehen, das Qt nur folgendes kann:
QString & replace ( const QRegExp & rx, const QString & after )
aber ich brauche ja ein:

Code: Alles auswählen

QString & replace ( const QRegExp & rx, const QRegExp & rx )
wenn ich das richtig sehe.

Mit dem Versuch:

Code: Alles auswählen

ui.label->setText( label->text().replace( QRegExp("*?<|?>*"), "(" ) );
könnte ich ohnehin nur ein Zeichen ersetzen, wenn ich alles richtig verstanden habe! Abgesehen davon funktioniert dieses Beispiel auch nicht!

Kannst du es vielleicht einmal versuchen, auch auf die Gefahr das du Müll schreibst ;-)
Schlimmer wie mein Versuch kann es ja nicht werden!

Gruß,

Whitefurrows

Verfasst: 4. Juni 2007 17:12
von upsala

Code: Alles auswählen

.replace("<", "(").replace(">", ")");

Verfasst: 4. Juni 2007 17:23
von bst
Hallo,

versuche das mal so:

Code: Alles auswählen

.replace( QRegExp("<([^<>]*)>"), "(\\1)")
cu, Bernd

Verfasst: 4. Juni 2007 18:01
von Whitefurrows
Hey, das hat ja super funktioniert :-), besten Dank!

Allerdings habe ich in einem anderen Fall das Problem, das ich auch "[" und "]" ersetzen muss. Jetzt habe ich versucht das ganze zu ändern in

Code: Alles auswählen

.replace( QRegExp("\[([^\[\]]*)\]"), "[\\1]")
leider ohne Erfolg. So grob habe ich ja verstanden was du da machst, aber für was genau das "(\\1)" ist habe ich absolut nicht verstanden. Es wäre nett wenn du mir noch ein paar Worte dazu sagen könntest, damit ich auch verstehe was du da machst und ich nicht das nächstemal wieder Fragen muss.

Verfasst: 4. Juni 2007 18:24
von Zandru
schau mal hier:
http://doc.trolltech.com/4.3/qregexp.ht ... uring-text

und aus http://doc.trolltech.com/4.3/qstring.html#replace :
For regular expressions containing capturing parentheses, occurrences of \1, \2, ..., in after are replaced with rx.cap(1), cap(2), ...

alles klar?

Verfasst: 4. Juni 2007 19:45
von Whitefurrows
Super, vielen Dank für eure Hilfe, es funktioniert jetzt.

Ich versuche es einmal zu Erklären und ihr Ergänzt bzw. Korrigiert mich bitte ;-) um zu sehen ob ich es auch verstanden habe. Es muss ja nicht bedeuten, wenn es funktioniert, dass ich es auch richtig verstanden habe!

"<" und das ">" am Anfang und Ende sind die Zeichen die ersetzt werden sollen

"[...]" in dieser rechteckigen klammer werden alle erlaubten Zeichen aufgeführt

"^" mit diesem Zeichen wird zum Ausdruck gebracht, das die folgenden Zeichen negiert werden, womit alle Zeichen außer "<" und ">" erlaubt sind

"*" durch diesen Stern sind alle gültige Zeichen hinter dem Ausdruck erlaubt

"(...)" diese Klammer wird gesetzt, weil mehrere Ausdrücke zusammen gefasst werden

"\\1" damit wird die erste capturing parenthese gewählt und vor bzw. nach dieser wird ein "(" und ")" eingefügt.

Zeichen die für einen Ausdruck verwendet werden (z.B."[...]"), aber als Zeichen genutzt werden sollen, können durch ein Escape sequence wie "\\..." genutzt werden, weshalb mein Beispiel zuvor mit einem "\" nicht funktioniert hat.

War das soweit jetzt richtig?

Verfasst: 4. Juni 2007 21:29
von bst
Abend,
War das soweit jetzt richtig?
Beinahe.

* bedeutet 0 oder mehrmals das vorangegangene Zeichen, so viele wie möglich.

Hier bezieht sich das also auf alle Zeichen außer < und >, bzw. außer [ und ].

(...) dient schon der Zusammenfassung von Teilausdrücken, das Wesentliche daran ist aber daß der geklammerte Teil in einem sogenannten SubMatch gespeichert wird auf den dann später via \nummer zugegriffen werden kann.

\1 im Ersatzstring ist der Inhalt des 1. SubMatches.

Innerhalb eines Strings werden ebenfalls \ als Spezialzeichen benutzt, deshalb muß man diese für QRegExp verdoppeln.
.replace( QRegExp("\[([^\[\]]*)\]"), "[\\1]")
Versuche es mal (ungetestet) mit:

Code: Alles auswählen

.replace( QRegExp("\\[([^\\[\\]]*)\\]"), "[\\1]")
Wobei dieses natürlich witzlos ist, da es ja nichts verändert.

cu, Bernd

Verfasst: 5. Juni 2007 07:26
von macman
Es sollte auch nicht vergessen werden, das bisher Genanntes nur funktioniert, wenn der Suchstring nur einmal im String vorkommt. Tritt er mehrmals auf, werden nur die äußeren Klammern ersetzt.

Verfasst: 5. Juni 2007 08:46
von bst
Morgen macman,

wie kommst Du darauf ?

Es werden alle Klammernpaare ersetzt, bei verschachtelten Klammern nur die innerste Ebene.

cu, Bernd
--

Code: Alles auswählen

#include <QDebug>
#include <QRegExp>
#include <QString>

int main(void)
{
	QRegExp rx("<([^<>]*)>");

	qDebug() << QString("a <1> b <234> c <5> d").replace(rx, "(\\1)");
	qDebug() << QString("a <1 b <2 c <345> d 6> e 7> f").replace(rx, "(\\1)");

	return 0;
} 

Verfasst: 5. Juni 2007 09:05
von macman
bst hat geschrieben:wie kommst Du darauf ?
Steht so in der Doku:
void QRegExp::setMinimal ( bool minimal )
Enables or disables minimal matching. If minimal is false, matching is greedy (maximal) which is the default.
For example, suppose we have the input string "We must be <b>bold</b>, very <b>bold</b>!" and the pattern <b>.*</b>. With the default greedy (maximal) matching, the match is "We must be <b>bold</b>, very <b>bold</b>!". But with minimal (non-greedy) matching, the first match is: "We must be <b>bold</b>, very <b>bold</b>!" and the second match is "We must be <b>bold</b>, very <b>bold</b>!". In practice we might use the pattern <b>[^<]*</b> instead, although this will still fail for nested tags.
bst hat geschrieben:Es werden alle Klammernpaare ersetzt, bei verschachtelten Klammern nur die innerste Ebene.
Stimmt, weil Du die Klammern im Suchstring negierst. Hab ich übersehen, Asche auf mein Haupt :-)

Verfasst: 5. Juni 2007 15:50
von Whitefurrows
Hallo,

noch einmal vielen Dank für die tolle Hilfe und Erklärungen, habe jetzt alles verstanden!

Gruß

Whitefurrows

Verfasst: 6. Juni 2007 11:55
von Whitefurrows
Hallo,

ich habe doch noch eine Frage. Ich wollte jetzt noch alle Zeilenumbrüche ersetzen und habe folgendes versucht:

Code: Alles auswählen

.replace( QRegExp("<([^<>]*)>|(\s)"), "(\\1)\\2<br>")
Wie erwartet hat es auch nicht richtig funktioniert, da ich eine OR Verknüpfung hatte. Ich brauche aber eine UND Verknüpfung, also "+" aber dann macht er garnichts.
Also wie bekomme ich eine UND Verknüpfung hin mit der ich in allen Strings die ein "<>" und ein oder mehrere "\n" bzw. "\r\n\" enthalten ersetzen kann?

Gruß

Whitefurrows

Verfasst: 6. Juni 2007 12:41
von bst
Hi Whitefurrows,

wenn Du alle Zeilenumbrüche ersetzen/löschen möchtest nimm vielleicht einfach noch einen 2. replace oder auch einen .remove hinzu.

Code: Alles auswählen

	QRegExp rx("<([^<>]*)>");
	QRegExp rx2("[\n\r]+");

	qDebug() << QString("a\n\n <1> b <2\n\r3\n\r4> c <5> d").replace(rx, "(\\1)").remove(rx2);
cu, Bernd