RegEx killt meinen Apache
Felix Riesterer
- programmiertechnik
0 Jonny 50 Gunnar Bittersmann0 Whouzuo
Liebe Mitlesende,
um PHP-seitig dafür zu sorgen, dass im Quelltext ein <input>-Element immer ein type-Attribut erhält, wollte ich mit einem regulären Ausdruck alle "unversorgten" Elemente finden. Dafür wollte ich look-ahead einsetzen. Jedoch "killt" folgender Ausdruck meinen Apache (der sich dann restartet):
if (preg_match_all(
'~(?is)(<input)((?!type=).)+>~',
$t->html,
$inputs
)) {
// etwas gefunden (passiert aber nicht wegen Absturz)
}
Liebe Grüße,
Felix Riesterer.
Hallo,
Dafür wollte ich look-ahead einsetzen. Jedoch "killt" folgender Ausdruck meinen Apache (der sich dann restartet): ...~(?is)(<input)((?!type=).)+>~
Vielleicht, weil das pcre.backtrack-limit erreicht wurde (ungünstiges Beispiel).
Sollte doch reichen, den lookahead 1x innerhalb <input> anzuwenden, etwas in der Art:
~(?is)<input(?![^>]+type=)[^>]+>~
lG, Jonny 5
Lieber Jonny 5,
toller Linktipp! Danke!
Sollte doch reichen, den lookahead 1x innerhalb <input> anzuwenden, etwas in der Art:
~(?is)<input(?![^>]+type=)[^>]+>~
Eben nicht! Der Lookahead-Ausdruck "verbraucht" kein Zeichen und bezieht sich aber exakt auf das nach ihm Folgende. Dein Code matcht auf Folgendes, was aber nicht beabsichtigt ist:
<input name="a1" type="button" />
Der Fehler in meinem Code war der Punkt. Also nicht so:
~(?is)(<input)((?!type=).)+>~
Sondern so:
~(?is)(<input)((?!type=)[^>])+>~
Herzlichen Dank für Deinen Denkanstoß!
Liebe Grüße,
Felix Riesterer.
Hallo Felix,
Eben nicht! Der Lookahead-Ausdruck "verbraucht" kein Zeichen und bezieht sich aber exakt auf das nach ihm Folgende. Dein Code matcht auf Folgendes, was aber nicht beabsichtigt ist:
<input name="a1" type="button" />
hmm, tut er das? Sehe ich jetzt nicht. Wusste auch nicht, was du mit der ersten capturing group (?is)(<input)...
genau beabsichtigst usw. Egal, Hauptsache es funktioniert für dich!
Lieber Jonny 5,
hmm, tut er das? Sehe ich jetzt nicht.
in Deinem Beispiel ist ein type-Attribut vorhanden. Dieses soll nicht ersetzt werden. Daher wird nicht gematcht. Works as designed.
Wusste auch nicht, was du mit der ersten capturing group
(?is)(<input)...
genau beabsichtigst usw.
Ich hätte auch im replace-Argument der Funktion den String ausschreiben können... anstatt '$1' zu notieren; hätte mir eine capturing group gespart - so what.
Egal, Hauptsache es funktioniert für dich!
Da bin ich eigentlich etwas idealistischer. Dieses "Hauptsache es funktioniert für dich!" klingt mir zu sehr nach quick&dirty. Das versuche ich in aller Regel zu vermeiden.
Liebe Grüße,
Felix Riesterer.
Hallo Felix,
ich wollte lediglich auf das Problem aufmerksam machen und einem Beispiel demonstrieren, dass es nicht nötig ist, den lookahead an jeder Position auszuführen, um:
wollte ich mit einem regulären Ausdruck alle "unversorgten" Elemente finden.
Mein Beispiel (?is)<input(?![^>]+type=)[^>]+> würde eben die <inputs ohne type= finden. Dachte das möchtest du.
Um nochmal zum Problem zurückzukehren: ~(?is)(<input)((?!type=).)+>~
Da Quantifier default greedy (gierig) sind, würde bei diesem rex und längerer Inputwurst alles, bis zum letzten >
gematcht werden und an (?!type=).)+
jeder Position der negative lookahead ausgeführt werden, was ein enormer Aufwand sein kann und eben auch nicht das erwünschte Ergebnis liefert.
Ev hätte es auch schon gereicht den Quantifikator bescheiden/faul zu machen: (?is)(<input)((?!type=).)+?>
um zu funktionieren, wäre aber auch unschön.
Dann schriebst du:
Der Fehler in meinem Code war der Punkt. Also nicht so:
~(?is)(<input)((?!type=).)+>~
Sondern so:
~(?is)(<input)((?!type=)[^>])+>~
Durch die Einschränkung auf Zeichen, die kein >
sind, wird natürlich die Menge an möglichen lookaheads auf ein konsumierbares Maß reduziert.
Dieses "Hauptsache es funktioniert für dich!" klingt mir zu sehr nach quick&dirty. Das versuche ich in aller Regel zu vermeiden
Ja, wenn du das jetzt so erwähnst, es klingt tatsächlich nicht gut, es geht doch um die Energie des Verstehens und nicht Funktionierens hier :)
Aus der Problembeschreibung ging für mich nicht hervor, wie genau dein Vorgehen geplant ist.
Wünsche einen erholsamen Sonntag,
Jonny 5
@@Jonny 5:
nuqneH
Mein Beispiel (?is)<input(?![^>+type=)[^>]+>] würde eben die <inputs ohne type= finden.
False positive: <input name=">" type="hidden">
Soll daraus <input name=" type="text">" type="hidden">
werden?
Suchmuster* zum Parsen von Markup sind selten eine gute Idee.
Qapla'
* Ein regulärer Ausdruck ist das hier nicht.
Lieber Gunnar Bittersmann,
Suchmuster* zum Parsen von Markup sind selten eine gute Idee.
richtig. Darum wird hier auch kein Markup geparst, sondern ein Muster nach fehlendem Textbaustein gesucht. Dazu ist ein echter Markup-Parser mit wesentlich mehr Schreibarbeit nötig, denn ich muss alle <input>-Elemente "finden" und daraufhin prüfen, ob sie kein type-Attribut haben... usw. Das Muster hilft mir, das mit einer einzigen Anweisung zu tun.
* Ein regulärer Ausdruck ist das hier nicht.
Mag sein. Warum sollte mich diese Spitzfindigkeit kümmern?
Liebe Grüße,
Felix Riesterer.
Lieber Gunnar Bittersmann,
False positive:
<input name=">" type="hidden">
wer sowas schreibt, ist selber schuld. Meine Meinung. Der Rest riecht sehr nach Elfenbeinturm.
Liebe Grüße,
Felix Riesterer.
Lieber Jonny 5,
Mein Beispiel (?is)<input(?![^>+type=)[^>]+>] würde eben die <inputs ohne type= finden. Dachte das möchtest du.
ja, das möchte ich. Im looka-ahead-Teil eine Zeichengruppe zu notieren, die mindestens ein nicht->-Zeichen definiert, hatte ich falsch verstanden, weil ich soetwas noch nie benutzt hatte. Jetzt erst verstehe ich, warum Dein Beispiel viel besser ist, als mein Ansatz.
COOL!!
Durch die Einschränkung auf Zeichen, die kein
>
sind, wird natürlich die Menge an möglichen lookaheads auf ein konsumierbares Maß reduziert.
Du hast völlig recht, dass diese Vorgehensweise noch immer nicht gut genug ist. Deine Lösung gefällt mir besser.
Ja, wenn du das jetzt so erwähnst, es klingt tatsächlich nicht gut, es geht doch um die Energie des Verstehens und nicht Funktionierens hier :)
Eben. Schon wieder etwas gelernt. Super! Vielen Dank!
Liebe Grüße,
Felix Riesterer.
@@Felix Riesterer:
nuqneH
um PHP-seitig dafür zu sorgen, dass im Quelltext ein <input>-Element immer ein type-Attribut erhält, wollte ich mit einem regulären Ausdruck alle "unversorgten" Elemente finden.
Ich geh wohl recht in der Annahme, dass dies im Zusammenhang mit deinem Styling-Problem steht?
Ich würd mich beim Styling lieber nicht auf das Vorhandensein optionaler Attribute verlassen (<input type="text">
, <button type="submit">
). Besser das Stylesheet so schreiben, dass es mit und ohne diese Attribute funktioniert.
Qapla'
Lieber Gunnar Bittersmann,
Ich geh wohl recht in der Annahme, dass dies im Zusammenhang mit deinem Styling-Problem steht?
exakt.
Ich würd mich beim Styling lieber nicht auf das Vorhandensein optionaler Attribute verlassen (
<input type="text">
,<button type="submit">
). Besser das Stylesheet so schreiben, dass es mit und ohne diese Attribute funktioniert.
Ich verlasse mich auf gar nichts, ich stelle mit Gewalt sicher, dass ein type-Attribut gegeben ist. Mein CMS wird entsprechend geschrieben, wozu da noch mit verklausulierten :not()-Selektoren arbeiten, wenn es nicht sein muss?
Trotzdem habe ich mich sehr über Deine Hinweise gefreut, da sie mich wieder etwas bisher noch nicht verstandenes gelehrt haben. Herzlichen Dank dafür!
Was die anderen HTML5-Typen für <input>-Elemente angeht, so muss ich ersteinmal sehen, wie und ob ich diese einsetze. Ich gewöhne mich erst langsam an HTML5 und versuche bei meiner Neuauflage meines CMS darauf einzugehen. HTML5 ist ja keineswegs ein verabschiedeter Standard, daher bin ich bei solchen Dingen sehr auf http://caniuse.com/ angewiesen.
Liebe Grüße,
Felix Riesterer.
@@Felix Riesterer:
nuqneH
Ich verlasse mich auf gar nichts, ich stelle mit Gewalt sicher, dass ein type-Attribut gegeben ist.
Damit baust du schlechte Wartbarkeit gleich mit ein.
Das Backend sollte nicht fragilen HTML-Code generieren, auf den das Stylesheet aufbaut, sondern das Stylesheet sollte möglichst robust (auch gegen spätere Änderungen am Markup) sein.
Mein CMS wird entsprechend geschrieben, wozu da noch mit verklausulierten :not()-Selektoren arbeiten, wenn es nicht sein muss?
Wozu optionale Attribute zur Pflicht erklären, wenn es nicht sein muss?
Es sollte nicht Aufgabe des CMS sein, sich um Styling-Probleme zu kümmern.
Was die anderen HTML5-Typen für <input>-Elemente angeht, so muss ich ersteinmal sehen, wie und ob ich diese einsetze.
Du solltest sie einsetzen, ab sofort. Zum einen ermöchen diese Eingabevalidierung, zum anderen wird bei Geräten mit virtueller Tastatur ein dem Eingabefeld angepasste angeboten.
HTML5 ist ja keineswegs ein verabschiedeter Standard
Das W3C-HTML5 ist immerhin Candidate Recommendation. Das WTFWG-HTML5 wird nie verabschiedeter Standard, weil living standard.
daher bin ich bei solchen Dingen sehr auf http://caniuse.com/ angewiesen.
In diesem Fall nicht. Es ist nicht so, dass die Eingabefelder mit den neuen Typen in alten Browsern nicht funktionieren würden. type-Attribute mit unbekannten Werten werden ignoriert, damit sind es vollständig funktionierende Texteingabefelder.
Qapla'
Om nah hoo pez nyeetz, Gunnar Bittersmann!
Das Backend sollte nicht fragilen HTML-Code generieren,
Genau. Z.B. name=">" ;-)
Matthias
@@Matthias Apsel:
nuqneH
Das Backend sollte nicht fragilen HTML-Code generieren,
Genau. Z.B. name=">" ;-)
Das ist durchaus valides HTML. Fragil nenne ich, sich auf eine Untermenge von HTML einzuschränken.
Qapla'
Lieber Gunnar Bittersmann,
Das Backend sollte nicht fragilen HTML-Code generieren,
Genau. Z.B. name=">" ;-)
Das ist durchaus valides HTML. Fragil nenne ich, sich auf eine Untermenge von HTML einzuschränken.
was bitte ist denn an <input name="user" type="text" />
genau "fragil"?? Und inwiefern ist es "fragil" im Gegensatz zu <input name="user" />
??
Wenn ich ein System schreibe, das HTML-Code ausspuckt, dann kann ich es so schreiben, dass es gewissen syntaktischen Kriterien folgt. Inwiefern diese HTML auf eine Untermenge reduzieren (z.B: weil grundsätzlich ein "vollständiges" Dokument mit <head> und <body> ausgeliefert wird), ist doch nur für die interne Funktionalität wesentlich, oder nicht?
Und was die Wartbarkeit angeht, so kommt es auf seine Plugin-Struktur an - das Grundgerüst ist sehr simpel gehalten. Und wenn ein Plugin seinen CSS-Code selbst "verwalten" darf (das System "merged" alle CSS-Dateien zu einer großen, die als einzige an den Browser geliefert wird), dann darf auch jedes Plugin (fast) machen, was es will (Präfixe sind etwas robustes).
Brauchst Du in Deinem Elfenbeinturm noch etwas Kaffee? Nur falls ich demnächst wieder daran vorbei gehe, dass ich Dir welchen mitbringen kann. :-)
Liebe Grüße,
Felix Riesterer.
@@Felix Riesterer:
nuqneH
was bitte ist denn an
<input name="user" type="text" />
genau "fragil"??
Daran nichts. Fragil ist, sich beim Stylen von Texteingabefeldern sich darauf zu verlassen, dass das optionale Attribut im Markup vorhanden ist und nicht etwa <input name="user" />
im HTML-Code steht.
Wenn ich ein System schreibe, das HTML-Code ausspuckt, dann kann ich es so schreiben, dass es gewissen syntaktischen Kriterien folgt.
Ja. Aber wenn du oder gar ein anderer später das System umbaut und nicht (mehr) weiß, dass das Stylesheet nur für eine gewisse Untermenge von HTML geschrieben worden ist, fliegt einem das Zeug um die Ohren.
Warum willst du diese Probleme nicht von vornherein vermeiden? Wegen der einen Zeile CSS, die du „nicht "schön"“ findest?
Brauchst Du in Deinem Elfenbeinturm noch etwas Kaffee?
„Earl Grey, heiß!“
Qapla'
Lieber Gunnar Bittersmann,
Ja. Aber wenn du oder gar ein anderer später das System umbaut und nicht (mehr) weiß, dass das Stylesheet nur für eine gewisse Untermenge von HTML geschrieben worden ist, fliegt einem das Zeug um die Ohren.
wenn derjenige tatsächlich am PHP-Code fummelt, dann sollte er auch die Kommentare im Quelltext lesen können. Das System ist so geschrieben, dass klar sein sollte, wie es funktioniert (dazu isses einfach zu simpel).
Warum willst du diese Probleme nicht von vornherein vermeiden? Wegen der einen Zeile CSS, die du „nicht "schön"“ findest?
Wenn ich nur die Elemente als solche selektieren wollte, wäre das nicht wesentlich unübersichtlicher. Aber wenn ich dann auch noch :hover und :focus und :before und :after einsetzen möchte, wird es das. Da mag ich das Konzept von CSS nicht sonderlich (muss mich endlich mal mit SASS oder dem Zeuch auseinandersetzen).
Brauchst Du in Deinem Elfenbeinturm noch etwas Kaffee?
„Earl Grey, heiß!“
Hehe. Du nicht Piccard, Du Bittersmann. Und seit wann stehen Klingonen auf Tee? War da nicht einmal etwas mit Raktajino oder so ähnlich? Wäre das nicht passender? Aber Tee kannste haben. Wie gesagt, sobald ich am Elfenbeinturm vorbei komme. ;-)
Liebe Grüße,
Felix Riesterer.
@@Felix Riesterer:
nuqneH
muss mich endlich mal mit SASS …
Ja.
… oder dem Zeuch auseinandersetzen).
Nein. ;-)
Und seit wann stehen Klingonen auf Tee?
Wie man doch die Menschen täuschen kann, wenn man ein paar anderssprachige Phrasen drischt. Eigentlich hab ich Spitze Ohren. ;-)
Wie gesagt, sobald ich am Elfenbeinturm vorbei komme. ;-)
Nichts gegen Elfenbein. Was wäre ein Klavier ohne weiße Tasten?
Qapla'
Om nah hoo pez nyeetz, Gunnar Bittersmann!
Und seit wann stehen Klingonen auf Tee?
Wie man doch die Menschen täuschen kann, wenn man ein paar anderssprachige Phrasen drischt. Eigentlich hab ich Spitze Ohren. ;-)
Matthias
Liebe Mitlesende,
um PHP-seitig dafür zu sorgen, dass im Quelltext ein <input>-Element immer ein type-Attribut erhält, wollte ich mit einem regulären Ausdruck alle "unversorgten" Elemente finden. Dafür wollte ich look-ahead einsetzen.
http://blog.codinghorror.com/regular-expressions-now-you-have-two-problems/
Für dein Problem ist ein entsprechender HTML/XML Parser viel besser geeignet.