On 2012-03-25 22:18, Thomas 'PointedEars' Lahn <
Point...@web.de> wrote:
> Peter J. Holzer wrote:
>> Thomas 'PointedEars' Lahn wrote:
[kleiner Ausflug in die Welt der formalen Sprachen]
>>
>> Allerdings sind Perl-Regexps keine regulären Ausdrücke im formalen Sinn,
>> sondern eine Erweiterung davon. Insbesondere kann man damit Klammern
>> matchen (Beispiele siehe FAQ seit ewigen Zeiten).
>
> Das ist nur teilweise richtig. Mit der rekursiven Erweiterung in Perl-
> Regexps bzw. PCREs muss für jede zusätzliche Rekursion Speicher reserviert
> werden. Klammersprachen können daher so nur eingeschränkt geparst werden.
> man perlre.
>
>> Die von diversen Leuten gebetsmühlenartig vorgetragene Begründung, dass
>> man mit regulären Ausdrücken keine kontextfreien Sprachen parsen könne,
>> ist daher eine Themenverfehlung.
>
> Ex falso quodlibet. Und ich jedenfalls habe das hier *so* _nicht_
> behauptet.
Um so schlimmer. Es wäre nämlich richtig. Nur für Perl irrelevant.
Allerdings frage ich mich dann, wozu Dein kleiner Ausflug in die Theorie
gut sein sollte. Bisschen Namedropping zum Einstand?
>> (Mal abgesehen davon, dass für viele Aufgabenstellungen (darunter das hier
>> diskutierte "jedes Vorkommnis eines bestimmten Strings ersetzen") ein
>> HTML-File als reguläre Sprache betrachtet werden kann, weil die
>> Verschachtelung der Elemente irrelevant ist.)
>
> Das ist grober Unfug.
Ach, Du ungläubiger Thomas!
#!/usr/bin/perl
use warnings;
use strict;
# schlürf
my $html = do { local $/ = undef; <> };
# tags ...
my $param = qr{ [-a-z]+ = " [^"]* " }x;
my $start_tag = qr{ < [a-z]+ (?: \s+ $param )* \s* /? > }x;
my $end_tag = qr{ </ [a-z]+ > }x;
my $comment = qr{ <!-- .*? --> }sx;
# normaler Text ...
my $pcdata = qr{ [^<]*? }x;
# Nested links in HTML sind verboten. Also beginnen wir mit einem
# Starttag <a ...> und endem beim ersten Endtag </a>. Ansonsten
# sind beliebige Start- und Endtags, Kommentare und Text erlaubt.
# Wir wollen darin auch nicht ersetzen, also behandeln wir das als
# Einheit:
my $link = qr{
<a (?: \s+ $param )* \s* >
(?:
$start_tag | $end_tag | $comment | $pcdata
) *?
</a>
}x;
# und jetzt kommen wir zum Eingemachten: Das ganze File ist eine Folge
# von dem ganzen Zeug, was wir oben definiert haben und dem Wort FOO,
# und nur letzteres wollen wir durch BAR ersetzen; Und wenn wir das
# gemacht haben, dann machen wir an der Stelle weiter.
$html =~ s{
\G
(
(?:
(?>
$link | $start_tag | $end_tag | $comment
)*
$pcdata
)*
)
FOO
}
{$1BAR}xg;
print $html;
__END__
Da sind einige offensichtliche Auslassungen drin. Sie zu finden und den
Code zu ergänzen, sei dem Studenten als Übungsaufgabe überlassen.
Was da nicht drin ist, ist irgendwas, was einen Kellerautomaten brauchen
würde. Das kann man auch als State-Machine schreiben (und müsste dann
nicht erst das Backtracking von perl austricksen).
>> Richtig ist allerdings, dass regexp-basierte Ansätze meistens fragil
>> und/oder unwartbar sind. Für ernsthaft eingesetzte Programme ist daher
>> auf jeden Fall ein Parser vorzuziehen.
>>
>> Allerdings hat Sven bereits im Ausgangsposting klargestellt, dass es ihm
>> nur um die intellektuelle Herausforderung geht und nicht darum, eine
>> praxistaugliche Lösung zu bekommen.
>
> Wie kommst Du auf dies schmale Brett?
Zitat:
| Ja, klar, es gibt fuer sowas auch geschicktere Loesungsmoeglichkeiten
| als regular expressions, nur hat mich hier jetzt doch mal die Neugierde
| gepackt :)
Das klingt für mich nicht so, als ob er eine "geschickte" Lösung sucht,
sondern er will wissen, ob das mit Regexp überhaupt geht, und wenn ja,
wie.
> Die intellektuelle Herausforderung ist es hier, eine praxistaugliche
> Lösung zu erhalten. Darum geht es auch Sven.
Deine Allwissenheit ist immer wieder bewunderswert. Was täten wir ohne
Dich! In den Newsgroups wäre nur Irrsal und Wirrsal.
> Dafür braucht man nicht unbedingt eine Parser-Klasse, aber *eine*
> RegExp reicht dafür nun einmal auch nicht aus
Doch, eine Regexp reicht, siehe oben. Als Praxistauglich würde ich das
allerdings nicht bezeichnen, obwohl es schnell geschrieben war (wenn man
davon absieht, dass ich mit (?>...) noch nicht so vertraut bin (gibts ja
erst seit 4 Jahren und ich bin ein alter Knacker und schon ein bisschen
verkalkt) und daher die richtige Stelle nicht auf Anhieb gefunden habe)
und eigentlich auch nicht schwer lesbar ist. Nur wenn man nicht-triviale
Änderungen machen will, wird's grindig.