Dies ist eine alte Version des Dokuments!


Regular Expressions (Reguläre Ausdrücke)

Regular Expressions sind aus Programmiersprachen wie Python oder Perl nicht wegzudenken. Da ihre direkte Verwendung in C++ nicht möglich ist, bietet Qt dafür eine Lösung.
Die Klasse QRegExp bietet eine objektorientierte Schnittstelle zur Verwendung von regulären Ausdrücken. Sie wird über folgenden Konstruktor instanziert:

QRegExp( const QString& pattern, Qt::CaseSensitivity cs = Qt::CaseSensitive, PatternSyntax syntax = RegExp )

pattern: Der eigentliche reguläre Ausdruck.
cs: Gibt an, ob der reguläre Ausdruck Groß-/Kleinschreibung berücksichtigt oder nicht.
syntax: Auswahl aus verschiedenen Syntaxen.

Praktischerweise gibt es auch eine Methode isValid() um zu prüfen, ob der angegebene Ausdruck gültig ist. Eine Fehlermeldung kann dabei über errorString() abgefragt werden.
Der Backslash, der fester Bestandteil des von regular Expressions ist, muss natürlich nach den C++-Regeln doppelt hintereinander vorkommen um einen gültigen Backslash im String zu erhalten.
Quantoren sind wie in Perl standardmäßig „gierig“, d.h. sie versuchen so viele Zeichen wie möglich in Anspruch zu nehmen. Das gebräuchliche Fragezeichen nach einem Quantor funktioniert in Qt nicht, sondern es muss die Methode setMinimal() mit true als Parameter aufgerufen werden.

Übereinstimmung

Zur Prüfung eines Strings auf Übereinstimmung mit dem regulären Ausdruck wird indexIn() verwendet.

int indexIn( const QString& str, int offset = 0, CaretMode caretMode = CaretAtZero ) const

str: String der auf Übereinstimmung geprüft werden soll.
offset: Offset vom Beginn des übergebenen Strings.
caretMode: Gibt an, an welcher Position ^ zutrifft, standardmäßig ist das der Beginn des Strings.
Rückgabewert: Index der Übereinstimmung, -1 wenn es keine Übereinstimmung gibt.

Die Methode captureTexts() gibt eine QStringList-Instanz zurück, die als erstes Element den gesamten String und die weiteren Gruppen enthält.

Das folgende Beispiel gibt die einzelnen Teile einer URL aus:

#include <QRegExp>
#include <QStringList>
#include <iostream>
 
int main()
{
  QString str( "https://proggen.org/" );
  QRegExp regex( "(\\w+)://(\\w+)\\.(\\w+)/" );
 
  regex.indexIn( str );
  QStringList matches = regex.capturedTexts();
 
  for( int i = 1; i < matches.size(); i++ )
    std::cout << "match " << (int) i << ": " << matches[i].toStdString() << std::endl;
 
  return 0;
}

Ausgabe:

match 1: https
match 2: proggen
match 3: org

Ersetzung

Wir können reguläre Ausdrücke auch zur Ersetzung von Texten in QString-Objekten verwenden. Die Methode liegt diesmal aber nicht in QRegExp, sondern direkt in QString.

QString& replace( const QRegExp& rx, const QString& after )

rx: Regulärer Ausdruck, der zum Vergleich verwendet wird.
after: Text, durch den der reguläre Ausdruck ersetzt wird.
Rückgabewert: Der neue String, in dem der reguläre Ausdruck durch den zweiten Parameter ersetzt wurde.

Wir können im String after auch Rück-Referenzen auf den regulären Ausdruck (\1, \2, ..; bzw. \\1, \\2, … nach C++-Syntax) verwenden.
Im nächsten Beispiel löschen wir alle HTML-Tags aus einem String:

#include <QRegExp>
#include <QStringList>
#include <iostream>
 
int main()
{
  QString str( "<h1><font color=#0000FF>proggen.org</font></h1>" );
  QRegExp regex( "<.+>" );
 
  regex.setMinimal( true );
  std::cout << str.replace( regex, "" ).toStdString() << std::endl;
 
  return 0;
}

Ausgabe:

proggen.org


So, nun wollen wir auch von Rück-Referenzen Gebrauch machen. Wir nehmen an wir haben Daten über Personen nach folgendem Format:

VornamePerson1,NachnamePerson1
VornamePerson2,NachnamePerson2
...

Wir hätten das jedoch gern umgekehrt und mit einem Semikolon als Trennzeichen, nämlich:

NachnamePerson1;VornamePerson1
NachnamePerson2;VornamePerson2
...

Nun zum Programm (der Einfachheit halber sind die Namen statisch festgelegt):

#include <QRegExp>
#include <QStringList>
#include <iostream>
 
int main()
{
  QString str(
      "Anton,Ansbach\n"\
      "Frank,Ferdinand\n"\
      "Karl,Klaasen\n"\
      "Otto,Ottendorf\n"\
      "Walter,Wurz\n"\
      "Zelda,Zett\n" );
  QRegExp regex( "(.+),(.+)\n" );
 
  regex.setMinimal( true );
  std::cout << str.replace( regex, "\\2;\\1\n" ).toStdString() << std::endl;
 
  return 0;
}

Ausgabe:

Ansbach;Anton
Ferdinand;Frank
Klaasen;Karl
Ottendorf;Otto
Wurz;Walter
Zett;Zelda