Die Auflösung ist (so doof es sich auch anhört), man kommt hier mit RegEx nicht weiter. Sprich: es ist nicht möglich, denn es exitiert kein regulärer Ausdruck, der diesen Sachverhalt allgemeingültig beschreiben kann. Man kann mittels RegExp nun mal nicht zählen oder sich etwas merken - ein RegEx kennt nur ein einzelnes Zeichen.
Anschaulich erklärt:
http://de.wikipedia.org/wiki/Reguläre_Sprache
Eine reguläre Sprache kann durch einen regulären Ausdruck beschrieben werden, durch eine reguläre Grammatik oder durch einen DFA/NFA (non/deterministic finite automaton).
Sprich: sobald man eine der 3 Darstellungen gefunden hat, weiß man, dass ein Sachverhalt regulär ist.
Beispiel: wir wollen einen Text suchen, in dem zwei mal ein a gefolgt von mindestens einem und beliebig vielen bs vorkommt. Gibt es dazu einen regulären Ausdruck? Wenn man das Problem mit einem NFA lösen kann, weiß man, dass es auch als regulärer Ausdruck darstellbar ist (und zwar kann man diesen aus der NFA Darstellung ablesen):
Code:
,------.
,-----. ,--+. :
/ \ a ,-. a / \ |b
( Start .........> ) .....> ( Ende ) |
\ / `-' \ / ;
`-----' `---\ /
`----'
Die aktuelle Aufgabe kann man nun so zusammenfassen: bezeichne den Code [ b ] mit a , den Code [ /b ] mit b und die ganze Resteingabe mit c. Wir haben:
a^n c* b^n mit n>=0 (das ^ Zeichen bedeutet hier: soviele Wiederholungen).
Sprich: wir müssen genausoviele bs wie as erkennen. Und dazu müssten wir uns irgendwie merken, wieviele davon wir gelesen haben.
Am anschaulichsten ist es, wenn man versucht den DFA/NFA dazu zu zeichnen: ein endlicher Automat kann sich weder merken was er bereits gelesen hat noch wieviel davon. Natürlich kann man bis zu einer gewissen Größe auch sowas erkennen:
Code:
,-----. ,--+.
/ \ a ,-.<-. / \
( Start -.....>. ) :c b ( Ende )
\ / `+' ; ``````>\ /
`--+--' `--' `-+-
|a ^
| |b
v ,-.<-. |
,+. c ( ) :c c ,+.
( ) -------->`+' ; .......>( )
`+' `--' `+'
| ^
|a |b
v |
,+. c ,-.<-. c ,+.
( )-------->( ) :c ......>( )
`+' `+' ; `+'
| `--' ^
|a |b
v ,-.<-. |
,+. c ( ) :c c ,+.
( )'''''''''>'`+' ;------->( )
`-' `--' `-'
und so weiter, für jede gewünschte Verschachtelungstiefe eben noch eine Ebene hinzufügen (wobei hier der Fall für c=1 fehlt, aber dann müsste ich neu zeichnen ;) )
RegExp dafür wäre:
ac*b|acc*cb|aacc*cbb|aaacc*cbbb
Damit erkennt man bis zu 3 fach verschachtelte Tags
D.h wenn man nur bestimmte Verschachtelungstiefe erkennen möchte, kann man durchaus eine Regex nutzen. Nur dass es alles andere als effizient sein wird - und bei dem Versuch, einen allgemeingültigen Ausdruck zu finden, verschendet man nur seine Zeit

.
Genauso "einsichtig" ist es, wenn man versucht das Ganze mittels regulärer Grammatik zu beschreiben, allerdings wäre das hier etwas zuviel des Guten
Formell lässt sich mittels dem Pumping-Lemma auch beweisen, dass dieses Problem nicht regulär beschrieben werden kann (naja, formell ist es auch die einzig tragbare Lösung - sonst kann man ja auch sagen: "nee, nur weil DU keinen reg. Ausdruck finden kannst, heißt es noch lange nicht, dass es keinen gibt!". Ist sogar die "Musteraufgabenstellung" im Beispielbeweis der Wikipedia
Zum Problem selbst: das sollte in die Klasse kontextfreier Sprachen fallen und lässt sich z.B mittels einem Kellerautomaten lösen. Und zwar gleich mit Beachtung der Reihenfolge [ i ][ b ]Text[ /b ][ /i ] :
ein Algorithmus wäre z.B
Code:
1.solange zeichen da sind -> lese_zeichen:
wenn zeichen=[ b ] push stack ' [ /b ]'
wenn zeichen=[ i ] push stack '[ /i ]'
wenn zeichen=[ /b ] muss auch pop stack='[ /b ]' sein, sonst fehler
wenn zeichen=[ /i ] muss auch pop stack='[ /i ]' sein, sonst fehler
wenn zeichen was anderes gehe zu 1.
keine_zeichen_da: ist stack nicht leer->fehler
(nicht allzu kritisch sein, ist schon länger her, dass ich Kellerautomaten machen durfte)
Wozu die ganze Quälerei nun soll: wie gesagt, der Auslöser war eine Diskussion heute auf dem Board - allerdings gab es auch vorher schon Posts, die in dieselbe Richtung gingen.
Man beachte übrigens die Formulierung "möglichst mittels einem regulären Ausdruck prüft" und "Schwierigkeit3 gilt nur, wenn man RegExp nutzen möchte". Es wurde also niemand wirklich gezwungen, RegExp zu verwenden
Es gibt noch einiges mehr an Beispielen (sobald man über triviale Aufgaben hinausgeht), die zwar mit gewohnten Mitteln relativ leicht lösbar ausschauen, es aber definitiv nicht sind. Es lohnt sich daher auch vorher nachzuforschen, ob die Aufgabe auch wirklich so lösbar ist.
Sonst gilt "2 hours of trial and error can save 10 minuts of manual reading"

. Zudem sollte es auch eine Anregung/Argument sein, nicht nur "lernen durch Ausprobieren" zu betreiben.