RegExp gesucht...
xwolf
- perl
0 Alexander Foken0 xwolf0 Alexander Foken0 xwolf
0 Andres Freund0 xwolf
0 Christian H.
Hi,
ich suche ein RegExp (kein schon vorhandenes Modul!) für folgendes Problem:
Ich benoetige eine Regular Expression mit dem ich einen
HTML-aehnlichen Argumentstring analysieren kann, der jedoch auch Quotes beherrscht.
Beispiele folgend.
Folgende Strings will ich bearbeiten:
<name1="wert1" name2="jx7jkakj js
">
(Dies ist noch kein Problem)
<irgendeinnamen = bla> (mit bla=[a-zA-Z0-9]*)
(Noch immer kein Problem)
<name="liste" value=("listitem1","listitem2","listitem3")>
(Nun wird es schon etwas knobeliger, was? Aber auch noch einfach lösbar.)
<name="wert1" value="dies ist ein "gequoteteter" Text">
(Und hier wird es schwer...)
<name="wert2" value2="dies ist ein "gequoteteter" <h1>H1</h1>-Text, mit HTML in sich.">
(Schach-Matt :))
Bei allem soll das Ergebnis ein Hash sein.
Obige Beispiel sollten dann folgenden Hash geben
%hash = (
name1 => "wert1",
name2 => "jx7jkakj js
",
irgendeinnamen => "bla",
liste => "(listitem1,listitem2,listitem3)",
name => "wert1",
value => "dies ist ein "gequoteteter" Text",
value2 => "dies ist ein "gequoteteter" <h1>H1</h1>-Text, mit HTML in sich."
)
Wer hat Ideen?
Ciao,
Wolfgang
Moin Moin !
Bah! Wer denkt sich so kranke Speichermethoden aus? Wenn das alte Daten oder Daten aus einer anderen Anwendung sind, hast Du verloren. Wenn Du es Dir selber ausgedacht hast, warum nicht XML oder wenigstens Standard-Encoding für kritische Zeichen (< > & " statt < > & ") ?
Ich denke, mit RegExps alleine wirst Du nicht weit kommen; da sind auch noch ein paar Schleifen, index(), usw. drin. Du brauchst sowas wie eine State Engine (Zustandsmaschine oder wie heißt dieses Informatiker-Theorie-Gerät auf deutsch?).
Alexander
Hi,
Bah! Wer denkt sich so kranke Speichermethoden aus? Wenn das alte Daten oder Daten aus einer anderen Anwendung sind, hast Du verloren. Wenn Du es Dir selber ausgedacht hast, warum nicht XML oder wenigstens Standard-Encoding für kritische Zeichen (< > & " statt < > & ") ?
Aehm...
es handelt sich um eine legetime HTML-aehnliche SPrachsyntax, die mit Hilfe von perl geparst werden soll.
Natuerlich wird es in der Praxis besch**t sein, wenn man ein Streing wie
deien hier hat:
<name="wert2" value2="dies ist ein "gequoteteter" <h1>H1</h1>-Text, mit HTML in sich.">
Aber das war ja auch nur ein Beispiel um zu zeigen, dass innerhalb des Arguments auch andere Variablen vorkommen sollen.
Ein echtes Beispiel, welches dann garnicht mehr so bescheuert waere, könnte so aussehen:
<include type="query" value="SELECT id FROM maintable WHERE name="test">
oder:
<if ((name="test") && (value =~ "<h1>"))>
<endif>
Ich denke, mit RegExps alleine wirst Du nicht weit kommen; da sind auch noch ein paar Schleifen, index(), usw. drin. Du brauchst sowas wie eine State Engine (Zustandsmaschine oder wie heißt dieses Informatiker-Theorie-Gerät auf deutsch?).
Finite-State-Machine :)
Nun, ich muss auch sagen, ich hab es teilweise schon genauso geloest dass ich 2 while()-Schleifen hintereinander habe und dann etwas genauer rein schau ob die Syntax der Ausdruecke passt.
Aber das schaut dann halt etwas bloed aus und ich denke, es müsste etwas kürzeres geben.
Ciao,
Wolfgang
Moin Moin !
Aehm...
es handelt sich um eine legetime HTML-aehnliche SPrachsyntax, die mit Hilfe von perl geparst werden soll.
Ja sicher, das bestreite ich gar nicht. Hast Du Dir das ausgedacht oder mußt Du mit dem Format leben?
Fall 1: Denke noch mal nach.
Fall 2: lies weiter. ;-)
Ein echtes Beispiel, welches dann garnicht mehr so bescheuert waere, könnte so aussehen:
<include type="query" value="SELECT id FROM maintable WHERE name="test">
Jau, und schon fällt Dein Parser auf die Nase, weil der Value nicht terminiert ist. Zähl mal die Gänsefüßchen ...
oder:
<if ((name="test") && (value =~ "<h1>"))>
<endif>
Du weißt, daß es für Perl eine fertige Template-Engine gibt?
Finite-State-Machine :)
genau.
Nun, ich muss auch sagen, ich hab es teilweise schon genauso geloest dass ich 2 while()-Schleifen hintereinander habe und dann etwas genauer rein schau ob die Syntax der Ausdruecke passt.
Aber das schaut dann halt etwas bloed aus und ich denke, es müsste etwas kürzeres geben.
Bei der Syntax nicht. Wenn Du etwas dichter an HTML arbeitest, geht es:
<demo name="foo.html" value="<html><body><h1 align="center">Hallo</h1>Quotes (") schreibt man in HTML als &quot;.<html>">
HTML-Escaping und Deescaping kannst Du z.B. im CGI-Modul borgen, der Code ist sehr sauber und schnell zu kopieren.
Alexander
Hi,
Ja sicher, das bestreite ich gar nicht. Hast Du Dir das ausgedacht oder mußt Du mit dem Format leben?
Ich hab an den Format mitgearbeitet :=)
Das Nebenproblem ist: Die Delphi-Gruppe hat es schon umgesetzt...Da kann ich mit Perl ja dann wohl nicht hinten anstehen, oder? :)
<include type="query" value="SELECT id FROM maintable WHERE name="test">
Jau, und schon fällt Dein Parser auf die Nase, weil der Value nicht terminiert ist. Zähl mal die Gänsefüßchen ...
Ich weiss, ist mir vorhin auch aufgefallen. Aber ich hatte gehofft du erkennst es als Tippfehler.
Ein Syntaxchecker ist schon dabei..
Du weißt, daß es für Perl eine fertige Template-Engine gibt?
Ja. Aber dies wird eine neuer Template-Parser, der etwas mächter ist als der vorhandene...(Und der nebenbei nicht auf Perl beschränkt ist).
Bei der Syntax nicht. Wenn Du etwas dichter an HTML arbeitest, geht es:
<demo name="foo.html" value="<html><body><h1 align="center">Hallo</h1>Quotes (") schreibt man in HTML als &quot;.<html>">
Ja, das ist natürlich die einfachste Möglichkeit:
1. Zuerst alle embeddeten und gequeoteten Tags suchen und
durch etwas anderes, am idealsten die HTML-Entities, ersetzen.
2. Normal parsen
3. Quotes rückübersetzen.
HTML-Escaping und Deescaping kannst Du z.B. im CGI-Modul borgen, der Code ist sehr sauber und schnell zu kopieren.
Och...
HTML::Entities
reicht völlig.
Ciao,
Wolfgang
Hi Wolfgang,
Wer hat Ideen?
Ich glaube nicht, dass das nur mit einem Regex zu lösen ist. Wenn es geht, wird das auf jeden Fall sehr umständlich.
Aber es sollte gehen, wenn du einen kleinen Parser baust. Ich hab das gemacht, weil ich anfangs dachte, es müsste doch irgendwie mit einem regex gehen, hab es aber dann doch so wie folgend gemacht.
########xwolf_regex.pl########
#!/usr/bin/perl -w
use strict;
use Data::Dumper;
my $string='<name="wert2" value2="dies ist ein "gequoteteter" <h1>H1</h1>-Text, mit HTML in sich.">';
my $test= parse_string($string);
print Dumper $test;
sub parse_string{
my $string=shift;
my $status;
$status->{value_started}=0;
$status->{save_name}=1;
$status->{save_value}=0;
$status->{current_value}='';
$status->{current_name}='';
$status->{backtrace}='';
while ($string=~m/(.)/g){ #Zeichenweise durchgehen. Könnte man besser mit einem Array machen, weis aber ehrlichgesagt nicht mehr, wie ich schnell einen string(perl) in ein Array verwandle.
if ($1 eq '='){
$status->{save_value}=1;
$status->{save_name}=0;
}
elsif ($1 eq '"'){
if ($status->{backtrace} eq '\'){
$status->{current_value}.=$1;
}
elsif($status->{value_started}==1){
$status->{save_value}=0;
$status->{save_name}=1;
$status->{value_started}=0;
$status->{values}->{$status->{current_name}}=$status->{current_value};
$status->{current_name}='';
$status->{current_value}='';
}
else{
$status->{save_name}=0;
$status->{save_value}=1;
$status->{value_started}=1;
}
}
elsif ($1 eq ' ' and $status->{value_started}!=1){
}
elsif ($status->{value_started}!=1 and ($1 eq '<' or $1 eq '>')){
}
else{
if ($status->{save_value}==1){
$status->{current_value}.=$1;
}
elsif ($status->{save_name}==1){
$status->{current_name}.=$1;
}
}
$status->{backtrace} = $1;
}
return %$status->{values};
}
######EOF#####
Ich denke mal so müsste es gehen. Allerdings hab ich das jetzt nicht ausführlich getestet, dh, da dürften sich noch einige Fehler verbergen. Auch werden momentan mehrfach vorkommende Attribute einfach überschrieben, was man aber dadurch beheben könnte, dass man die Ergebnisse nicht in einem Hash sondern einem Array speichert.
Falls du ausführlichere Komentare wünscht, ist das kein Problem, nur will ich jetzt erst mal was essen.
Grüße Andres Freund
Hi,
hm...die Lösung hat was für sich..
Allerdings müsste ich dann den backtrace-Algorithmus, also den Punkt wenn ich auf ein Quote-Zeichen treffe, noch ergänzen um andere Möglichkeiten, wie um < und > usw.
Ich überlegs mir mal.
Danke für die Idee!
Ciao,
Wolfgang
Hallo xwolf,
ich suche ein RegExp (kein schon vorhandenes Modul!) für folgendes Problem:
Ich benoetige eine Regular Expression mit dem ich einen
HTML-aehnlichen Argumentstring analysieren kann, der jedoch auch Quotes beherrscht.
Schau dir das mal an: http://forum.de.selfhtml.org/archiv/2003/6/48629/#m266275
Gruß
Christian