regulärer Ausdruck
Heinz
- programmiertechnik
Hallo!
ich möchte gerne folgendes in einer HTML-Datei finden
<h1>
<h1 style="...">
aktuell ist mein regulärer Ausdruck wie folgt:
grep -n "<[a-zA-Z0-9]+>" test.txt
damit wird "<h1>" gefunden, jedoch nicht "<h1 style="...">"
wenn ich den regulären Ausdruck wie folgt abändere
grep -n "<.*+>" test.txt
findet er leider auch "< xyz >"
Wie müßte ich den regulären Ausdruck abändern, damit er "< irgendetwas bis zum nächsten >" findet?
Heinz
Wie müßte ich den regulären Ausdruck abändern, damit er "< irgendetwas bis zum nächsten >" findet?
<[^>]+>
(Zeichenklasse mit [], darin verneint mit ^ ein >, also alles außer >, von dieser Zeichenklasse eins oder mehrere Zeichen)
nicht zu verwechseln mit
<°(((><
Mathias
Guten Abend,
Wie müßte ich den regulären Ausdruck abändern, damit er "< irgendetwas bis zum nächsten >" findet?
<[^>]+>
(Zeichenklasse mit [], darin verneint mit ^ ein >, also alles außer >, von dieser Zeichenklasse eins oder mehrere Zeichen)
Beachte auch, dass hier grep benutzt wird, also die Ausführung in einer Shell zu vermuten ist. Da müssen die Zeichen < und > auch escaped werden, weil sie sonst von der Shell gefressen werden.
Gesundheit!
Dr. Bit
<[^>]+>
so ganz funktioniert der Ausdruck leider nicht.
cat test.txt
<b>
<h1>
<h1>
<b>
<h1 style="">
< test >
<b style="...">test</b>
</b>
h1 < h2 h2 > h3
grep "<[^>]+>" test.txt
<h1>
<b>
<h1 style="">
< test >
"< test >" sollte er nicht finden
Wie schliesse ich ">" aus? [^>] ist leider nicht ganz richtig.
Wie kann/muss ich den regulären Ausdruck erweitern, dass nach < und vor > kein Leerzeichen stehen darf?
der nachfolgende Ausdruck findet leider zu wenig
grep "<[^\ ][^>]+[^\ ]>" test.txt
<h1 style="">
Heinz
der nachfolgende Ausdruck findet leider zu wenig
grep "<[^\ ][^>]+[^\ ]>" test.txt
Klar, weil mindestens drei Zeichen zwischen < und > stehen müssen.
Wenn du es genauer haben willst, dann musst du die Start-Tag-Syntax genauer mit einem regulären Ausdruck (vereinfacht) abbilden. Ein Start-Tag besteht aus einem <, darauf folgen einige Buchstaben und ggf. Zahlen. Dann ist der Tag zuende oder es kommen noch Attribute. Die fangen mit Whitespace an, dann kommt der Attributname aus Buchstaben, dann das Gleichheitsszeichen, dann der Attributwert eingefasst in " oder '. Dieses Schema kann beliebig häufig. Schließlich steht am Ende >.
Könnte z.B. so aussehen:
<[a-z\d]+(\s+[a-z]+=("[^"]*"|'[^']*'))*>
Das nur als Beispiel, nicht als Fertiglösung. Eine solche kannst du mit den Hinweisen aber erarbeiten.
Mathias
@@molily:
Du hast ’ne ganze Menge Nichts vergessen:
Dann ist der Tag zuende oder es kommen noch
optionaler Whitespace oder
Attribute. Die fangen mit Whitespace an, dann kommt der Attributname aus Buchstaben, dann
optionaler Whitespace, dann
das Gleichheitsszeichen, dann
optionaler Whitespace, dann
der Attributwert eingefasst in " oder '. Dieses Schema kann beliebig häufig. Schließlich steht am Ende
optionaler Whitespace und
.
Live long and prosper,
Gunnar
Als ich meinen Beitrag schrieb, wusste ich genau, dass jemand namens Gunnar Bittersmann mich missversteht und darauf anspringen wird. Und ja: Ich bin mir völlig dessen bewusst, was du schreibst. Aber: Ich habe das absichtlich weggelassen. Warum, ergibt sich aus keinem technischen Erfordernis, sondern aus der Sprechsituation hier im Forum hier im Thread. Und ich würde es wieder tun. Ich habe nicht umsonst angemerkt, dass ich nicht die offizielle mögliche SGML-Syntax wiedergebe, sondern eine vereinfachte Variante. Weil es mir überhaupt nicht darum ging, eine Fertiglösung zu bieten oder die mögliche SGML-Syntax zu erklären, sondern einen Anstoß zu geben. Dass die Beispiel-RegExp »nur« auf einen Großteil des HTMLs zutrifft, es vom Einsatzzweck abhängt, ob sie ausreichend ist, und es noch viel genauer, flexibler und damit komplizierter geht, hätte ich durchaus noch einmal betonen können. Aber wenn der Fragesteller diesen regulären Ausdruck verstanden hat und damit selbstständig weiterarbeiten kann, und darum ging es mir vor allem, kann ich ihn immer noch vor komplexere Aufgaben stellen. Insofern halte ich dein Posting für wenig hilfreich und der Situation unangemessen.
Mathias
Hi!
<[a-z\d]+(\s+[a-z]+=("[^"]*"|'[^']*'))*>
er kann so nicht aussehen, da du <> und " verwendest
ich muss dafür jeweils folgende Zeichen verwenden
< => <
=> >
" => "
[^"] <--- wie muss ich das schreiben, damit "nicht &qout;" da drin steht?
[^"] bedeutet doch, dass nicht die &, q, u, o, t und ; vorkommen dürfen
Ich scheiter gerade an dieser Negation.
Heinz
[^"] <--- wie muss ich das schreiben, damit "nicht &qout;" da drin steht?
Das geht nicht mit negativen Zeichenklassen. Da kannst du nur .* für beliebig viele Zeichen verwenden und ein ? dahinter, damit der Teil nicht »greedy« ist, also nur soviele Zeichen umspannt, bis ein " folgt: ".*?"
Solche Konstruktionen waren bei mir aber immer trotz ungreedy-Flag unzuverlässig... vielleicht kennt jemand eine bessere Möglichkeit.
Mathias
Hi!
[^"] <--- wie muss ich das schreiben, damit "nicht &qout;" da drin steht?
Das geht nicht mit negativen Zeichenklassen. Da kannst du nur .* für beliebig viele Zeichen verwenden und ein ? dahinter, damit der Teil nicht »greedy« ist, also nur soviele Zeichen umspannt, bis ein " folgt: ".*?"
Solche Konstruktionen waren bei mir aber immer trotz ungreedy-Flag unzuverlässig... vielleicht kennt jemand eine bessere Möglichkeit.
mein Ausdruck sieht jetzt wie folgt aus
grep -wE "</?[a-zA-Z]+[a-zA-Z0-9]*.*?>" test.txt
ob ich damit alles abgedeckt habe?
Warum findet
grep -wE "</?[:alpha:]+[:alnum:]*.*?>" test.txt
folgende Zeile nicht "<b>"?
Heinz
Hi!
Warum findet
grep -wE "</?[:alpha:]+[:alnum:]*.*?>" test.txt
folgende Zeile nicht "<b>"?
es wäre super, wenn mir noch jemand ein Tipp geben könnte, warum diese Zeile nicht "<b>" findet.
Danke!
Heinz
@@Heinz:
grep -wE "</?[:alpha:]+[:alnum:]*.*?>" test.txt
Was soll '.*?' bewirken?
Live long and prosper,
Gunnar
Hi!
grep -wE "</?[:alpha:]+[:alnum:]*.*?>" test.txt
Was soll '.*?' bewirken?
jedes beliebe Zeichen beliebig oft aber Nongreedy Matching
Heinz
Was soll '.*?' bewirken?
jedes beliebe Zeichen beliebig oft aber Nongreedy Matching
Das widerspricht sich.
Struppi.
Was soll '.*?' bewirken?
jedes beliebe Zeichen beliebig oft aber Nongreedy Matching
Das widerspricht sich.
Wieso das?
Mathias
Was soll '.*?' bewirken?
jedes beliebe Zeichen beliebig oft aber Nongreedy Matching
Das widerspricht sich.
Wieso das?
Ein beliebiges Zeichen soll so oft wie möglich gefunden werden, aber nicht gierig, was soll das nicht gierig bewirken?
Struppi.
Ja ok, ich seh's ein.
Struppi.
Ein beliebiges Zeichen soll so oft wie möglich gefunden werden, aber nicht gierig, was soll das nicht gierig bewirken?
Macht natürlich nur Sinn, wenn dahinter der Reguläre Ausdruck noch weitergeht, sodass .*? nur soweit reicht, bis das dahinter das erste Mal matcht.
"bla ende bla ende".match(/.*ende/) == "bla ende bla ende" // greedy
"bla ende bla ende".match(/.*?ende/) == "bla ende" // non-greedy
Mathias
Hi!
kannst du mir sagen, warum
grep -wE "</?[:alpha:]+[:alnum:]*.*?>" test.txt
"<b>" nicht erkennt?
grep -wE "</?[a-zA-Z]+[a-zA-Z0-9]*.*?>" test.txt
erkennt ihn.
[:alnum:] ist doch das gleiche wie [a-zA-Z0-9], oder?
Heinz