PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : QRegExp



hpf
30-12-2008, 17:15
Hallo erstmal,
ich habe ein Problem mit der Klasse QRegExp, sie will nicht das tun, was sie soll.
Die Funktion soll einen String, welcher eine Website beinhaltet auf links prüfen,
der Ausdruck funktioniert, wenn ich ihn mit dem Tool Visual REGEXP benutze, allerdings nicht mit der Klasse QRegExp.

Hier mal mein code:



QRegExp m_regexp ("<a.*? href=\"(.*?)\".*?>.*?</a>", Qt::CaseInsensitive);
int pos = 0;
int count = 0;

while ((pos = m_regexp.indexIn(data, pos)) != -1) {
m_matches << m_regexp.cap(1);
pos += m_regexp.matchedLength();
count++;
}

std::cout << "-----------------------------------------------------Matches "<< count <<"--------------------------------------------------------------------------------" << std::endl;

for(int i=0; i<m_matches.size(); i++){
std::cout << "-------------------------------------------------------------"<< i <<"--------------------------------------------------------------------------------" << std::endl;
std::cout << "match: " << m_matches.at(i).toAscii().data() << std::endl;
}

return m_matches;


QT sagt nun immer, dass er keine Matches gefunden hat, obwohl das eben erwähnte andere tool in den selben Daten 15 Matches hatte.

Hoffentlich kann mir einer verraten warum der das net tut ? :(

mfg
hpf

undefined
30-12-2008, 17:34
Zu wenig Slashes das sollte dir aber auch der Compiler melden.

QRegExp m_regexp ("\\<a.*? href=\"(.*?)\".*?\\>.*?\\<\\/a\\>", Qt::CaseInsensitive);

hpf
30-12-2008, 17:40
Hallo undefined,
zuersteinmal herzlichen Dank für die schnelle Antwort, aber leider hilft auch das escapen net :( habe es eben nochmal ausprobiert, aber der String war (zumindest compiler technisch) korrekt escaped.
Hast du eventuell noch ne andere Idee ?
mfg
hpf

jeebee
30-12-2008, 18:01
Soweit ich in der Doku von Qt sehe, matcht QRegExp standardmässig greedy und versteht die Perl-RegExp non-greedy quantifiers mit '?' nach dem eigentlichen quantifier nicht. Du kannst das Verhalten mit QRegExp::setMinimal ( bool minimal ) ändern.

siehe auch http://doc.trolltech.com/4.4/qregexp.html#setMinimal

HTH
jeebee

hpf
30-12-2008, 18:25
Hallo,
auch die variante mit setMinimal(true) habe ich nun ausprobiert, leider liefert auch diese keine neuen Resultate :(
So langsam verzweifle ich noch an QRegExp, das kann doch net sein, dass das was ich vorhabe nicht realisierbar ist.
Nur finde ich leider den Fehler net :(

mfg
hpf

jeebee
30-12-2008, 19:37
naja, die ? hinter den * musst du dann natürlich auch noch wegnehmen.

undefined
31-12-2008, 09:41
Naja ich würde so etwas auch nicht mit einem Regexp machen.
QDomDocument ist bei HTML dafür besser geeignet.


int i;
QDomDocument dom;
if ( dom.setContent ( &stream ) )
{
QDomNodeList list = dom.elementsByTagName ( "a" );
for ( i = 0; i < list.size(); ++i )
{
QDomElement node = list.at ( i ).toElement();
if ( ! node.hasAttribute ( "href" ) )
// ....
}

Ab Qt 4.5 wird so etwas noch einfacher, wenn der interne XSLT Prozessor einzug erhält.

hpf
01-01-2009, 15:44
hallo,
vielen dank nochmal für eure hilfe.
Ich habe es nun ans laufen bekommen, ich musste den regulären ausdruck anpassen, mich wundert nur, dass er mit dem anderen tool lief.

Der aktuelle ausdruck lautet :
"<a.* href=\"(.[^\"]*)\"(.[^<]*)</a>" (funktioniert unter verwendung von setMinimal(true) ).

@undefined
Danke für den Tipp mit dem Dom parser, aber auf den meisten seiten kehrt setContent mit nem fehler zurück, somit scheidet diese lösung leider aus.

mfg
hpf

jeebee
01-01-2009, 16:30
wie ich schon gesagt habe, brauchst du ja Ausdrücke wie ".*?"; Bei diesen Ausdrücken verwendest du Perl-Regex-Syntax welche besagt, dass ein ? hinter einem * oder + diesen Quantifier nicht-gierig macht, d.h. wenn du z.B. auf den String "blubb <em>strong</em> bla" den Regex "<.*> anwendest, wird "<em>strong</em>" gematcht. Mit dem Regex "<.*?>" matchst du "<em>" und "</em>". Anscheinend versteht nun QRegExp dieses nicht-gierige Verhalten nicht und interpretiert "<.*?>" nicht als
matche ein '<' gefolgt von möglichst wenigen beliebigen Zeichen bis zum nächsten '>' sondern als
matche ein '<' gefolgt von möglichst vielen Zeichen bis zu einem '?' gefolgt von einem '>' (bin nicht sicher ob das exakt so stimmt...)

Dein anderes Tool hingegen versteht offensichtlich die oben erläuterte Syntax, weswegen dein Ausdruck funktioniert.

QRegExp::setMinimal( bool minmal ) ändert das Verhalten der Quantifier '*' und '+' in deinem Ausdruck global in das nicht-gierige (möglichst wenige Zeichen) Verhalten.

HTH jeebee