Ich benutze eine Regex, um einige BBCode zu analysieren, also muss die Regex rekursiv arbeiten, um auch Tags in anderen zu finden. Der Großteil des BBCode hat ein Argument, und manchmal wird es zitiert, wenn auch nicht immer.If-else in rekursiver Regex funktioniert nicht wie erwartet
Ein vereinfachtes Äquivalent der regex I (mit HTML-Style-Tags die entweichenden benötigt reduzieren) bin mit dieser ist:
'~<(\")?a(?(1)\1)> #Match the tag, and require a closing quote if an opening one provided
([^<]+ | (?R))* #Match the contents of the tag, including recursively
</a>~x'
Allerdings, wenn ich einen Test-String haben, die wie folgt aussieht:
<"a">Content<a>Also Content</a></a>
sie paßt nur die <a>Also Content</a>
, weil, wenn er versucht, vom ersten Tag, die ersten passenden Gruppe zu entsprechen, \1
, auf "
gesetzt ist, und das ist nicht ov Er wird geschrieben, wenn die Regex rekursiv ausgeführt wird, um dem inneren Tag zu entsprechen, was bedeutet, dass es nicht übereinstimmt und dass Regex fehlschlägt, weil es nicht zitiert wird.
Wenn ich stattdessen konsistent entweder Anführungszeichen verwende oder nicht, funktioniert es gut, aber ich kann nicht sicher sein, dass das der Fall mit dem Inhalt sein wird, den ich analysieren muss. Gibt es eine Möglichkeit, dies zu umgehen? obwohl
"~\[spoiler\s*+ #Match the opening tag
(?:=\s*+(\"|\')?((?(1)(?!\\1).|[^\]]){0,100})(?(1)\\1))?+\s*\] #If an option exists, match that
(?:\ *(?:\n|<br />))?+ #Get rid of an extra new line before the start of the content if necessary
((?:[^\[\n]++ #Capture all characters until the closing tag
|\n(?!\[spoiler]) Capture new line separately so backtracking doesn't run away due to above
|\[(?!/?spoiler(?:\s*=[^\]*])?) #Also match all tags that aren't spoilers
|(?R))*+) #Allow the pattern to recurse - we also want to match spoilers inside spoilers,
# without messing up nesting
\n? #Get rid of an extra new line before the closing tag if necessary
\[/spoiler] #match the closing tag
~xi"
Es gibt ein paar andere Fehler mit ihm auch
Der vollständige Regex, die ich verwende, ist [spoiler]content[/spoiler]
, [spoiler=option]content[/spoiler]
und [spoiler="option"]content[/spoiler]
, anzupassen.
Die zweite Lösung funktioniert leider nicht richtig auf der komplexeren Regex, die ich für den tatsächlichen Code verwende, aber die erste Lösung sollte funktionieren. – JackW
@StormDrive vielleicht sollten Sie Ihre volle Regex in diesem Fall posten. –
Ich habe es zu der Frage hinzugefügt, obwohl es ziemlich hässlich ist. – JackW