PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : RegEx mit beliebiger Reihenfolge


DanMan
2010-07-25, 11:11:56
Wie schreibt man einen regulären Ausdruck, der ein Suchmuster auf eine Zeile anwendet, wenn zuvor ein anderer Treffer gelandet wurde?

Konkret will ich aus einem HTML Link-Tag den Inhalt des href-Attributs ziehen, wenn im rel-Attribut ein bestimmter Text steht.

Das große Problem dabei ist, dass man nicht wissen kann, welches Attribut zuerst im Quelltext kommt. Ich kann also z.B. nicht einfach zuerst nach "stylesheet" suchen, und dann erst nach "href", weil das "href" ja zuerst drinstehen kann.

Ich nehme mal an, dass es dafür die lookaround Anweisungen gibt, aber irgendwie wollte es nicht hinhauen. Kann mir jemand helfen (Perl Syntax wär ideal)?

DanMan
2010-07-25, 12:51:51
Ich hab jetzt ein erstes Ergebnis:
<link[^>]+(?:(?=shortcut icon)[^>]+href="(.+?)")|(?:href="(.+?)".+(?=shortcut icon)[^>]+)
Was mich daran noch stört ist, dass ich 2 capturing groups habe, und ich vorher nicht wissen kann, welche gefüllt sein wird. Ich könnte natürlich einfach alle leeren Einträge im Ergebnis rausfiltern, aber schöner wärs, wenns erst garnicht drin landet.

Wie könnte man also die capturing groups auf eine reduzieren?

PatkIllA
2010-07-25, 13:03:12
Für welche Sprache überhaupt?
Ich würde ja erstmal beim Parser ansetzen. Da ist man meist eher unabhängig von der Attributreihenfolge.

DanMan
2010-07-25, 13:47:27
Für welche Sprache überhaupt?
Ich würde ja erstmal beim Parser ansetzen. Da ist man meist eher unabhängig von der Attributreihenfolge.
Naja, ich benutze einfach die stinknormale PHP RegEx Engine mit Pearl Syntax über preg_match(), weil ich denke, dass ein XML Parser wohl (noch) langsamer wäre.

Falls es einer testen will: http://gskinner.com/RegExr/
Hier ein Beispieltext:
<meta NAME="robots" CONTENT="follow">
<link href="favicon.ico" rel="shortcut icon">
<link rel="shortcut icon" href="favicon.ico">
<link rel="index" href="ref.url.php" />
<link href="function.http-build-query.php" rel="prev" />
<title>blabla blablalba</title>

PatkIllA
2010-07-25, 13:52:43
Ich bin oft erstaunt wie schnell die XML Parser doch sind und habe mich schon ein paar mal verrrant, weil das erstellen von RegAusdrücken nicht gerade billig ist.
Bei HTML hat man wohl eher das Problem, dass es halt oft kein XML ist.

Coda
2010-07-25, 14:08:02
Man kann HTML nicht per RegEx parsen. Das wird manchmal funktionieren, aber sehr oft nicht.

Zur Erheiterung: http://stackoverflow.com/questions/1732348/regex-match-open-tags-except-xhtml-self-contained-tags/1732454#1732454

DanMan
2010-07-25, 14:25:20
Ja, ich machs ja auch nicht gerne, vor allem weil mir beim Begriff "reguläre Ausdrücke" schon ein kalter Schauer den Rücken hinunter läuft. Aber was soll ich dann nehmen? PatkIllA hat doch recht - oft ist es kein XML sondern irgendein Brei.

Ich hab aufgrund des Parser-Einwands meinen Vorgang nochmal hinterfragt und vielleicht wirds ja was, wenn ich Tidy mit einem XML Parser kombiniere. Oder was wär euer Vorschlag?

@Coda: Chuck Norris can parse HTML with regex. ;)

Monger
2010-07-25, 14:46:14
Es gibt echte HTML Parser. Wie gesagt: HTML ist eben kein XML, also reicht ein XML Parser nicht.

Und noch zu den regulären Ausdrücken: ich kenn zwar auch Lookahead/behind und Conditions, aber das wird sehr schnell sehr hässlich - und möglicherweise auch langsam.

Regex ist ja keine Programmiersprache ;) , und was du versuchst, ist eigentlich eine Form von logischer Verknüpfung. Du tust dir wahrscheinlich wesentlich leichter, wenn du aus einem regulären Ausdruck zwei machst, und dann die restliche Logik in Perl ausprogrammierst.

Coda
2010-07-25, 14:59:27
Für welche Sprache soll das ganze überhaupt sein?

Monger
2010-07-25, 15:06:04
Für welche Sprache soll das ganze überhaupt sein?
Ich hab mal Perl angenommen, weil Perl Syntax gewünscht war.

Coda
2010-07-25, 15:16:26
Perl-RegEx-Syntax wird praktisch überall eingesetzt. Genauer gesagt verwenden alle PCRE, oder sind kompatibel dazu.

PatkIllA
2010-07-25, 15:17:25
Naja, ich benutze einfach die stinknormale PHP RegEx Engine mit Pearl Syntax über preg_match(),
PHP

DanMan
2010-07-25, 15:20:28
Regex ist ja keine Programmiersprache ;) , und was du versuchst, ist eigentlich eine Form von logischer Verknüpfung. Du tust dir wahrscheinlich wesentlich leichter, wenn du aus einem regulären Ausdruck zwei machst, und dann die restliche Logik in Perl ausprogrammierst.
Ja, hatte ich auch schon überlegt, es in 2 Schritten zu machen (erst die Zeile mit "shortcut icon" finden, und dann das href Atrribut der Zeile auszulesen). Aber das wär ja zu einfach. ;)

Nach noch mehr ruuumgegoogle durfte ich herausfinden, dass die PHP (darum gehts) DOM Klasse (http://de.php.net/manual/de/book.dom.php) (die eigentlich für XML gedacht ist) auch eine loadHTML() Methode besitzt. Mal schauen ob mir das weiterhilft.

Danke jedenfalls fürs Blick in die richtige Richtung lenken. ;)

PatkIllA
2010-07-25, 15:30:36
Gibt es sowas auch für andere Sprachen?

DanMan
2010-07-25, 15:51:30
Gibt es sowas auch für andere Sprachen?
In dem Link, den Coda gepostet hat stehen in den Kommentaren einige Libraries für verschiedene Sprachen. Für Python soll wohl das gut sein: http://www.crummy.com/software/BeautifulSoup/

Hier noch ein paar für PHP (gerade gefunden, auch aus den Kommentaren):
http://www.siteroller.net/projects/domparser/ (http://github.com/siteroller/domparser)
http://querypath.org/
http://simplehtmldom.sourceforge.net/

Coda
2010-07-25, 16:01:55
Für PHP gibt es eine HTML5-Parser-Library:
http://code.google.com/p/html5lib/