Ich habe diesen Code:

var s_1 = 'blabla [size=42]the answer[/size] bla bla blupblub';
var s_2 = 'blabla [size=42]the answer[/size] bla bla blupblub [size=32] 32 [/size]';

alert('Test-String:\n' + s_1 + '\n\nReplaced:\n' + size(s_1));
alert('Test-String:\n' + s_2 + '\n\nReplaced:\n' + size(s_2));


function size(s) {
    var reg = /\[size=(\d{1,2})\]([\u0000-\uFFFF]+)\[\/size\]/gi;
    s = s.replace(reg, function(match, p1, p2) {
        return '<span style="font-size: ' + ((parseInt(p1) > 48) ? '48' : p1) + 'px;">' + p2 + '</span>';
    })
    return s;    
}

Es soll alle Vorkommen der "[size = nn] [/ size]" - Tags ersetzen, aber es ersetzt nur die äußeren. Ich kann nicht herausfinden, wie ich sie alle ersetzen kann. (Bitte empfehlen Sie nicht, ein PHP-Skript zu verwenden. Ich hätte gerne eine Live-Vorschau für den mit BB-Code formatierten Text.)

Probier es aus

0
John Doe 17 Okt. 2012 im 18:28

3 Antworten

Beste Antwort

Übereinstimmende (möglicherweise verschachtelte) BBCode-Tags

Ein Multi-Pass-Ansatz ist erforderlich, wenn die Elemente verschachtelt sind. Dies kann auf zwei Arten erreicht werden; Übereinstimmung von innen nach außen (kein rekursiver Ausdruck erforderlich) oder von außen nach innen (was einen rekursiven Ausdruck erfordert). (Siehe auch meine Antwort auf eine ähnliche Frage: PHP, verschachtelte Vorlagen in preg_replace) Da die Javascript-Regex-Engine dies jedoch nicht tut Rekursive Ausdrücke unterstützen. Der einzige Weg, dies (korrekt) mit Regex zu tun, ist von innen nach außen. Unten finden Sie eine getestete Funktion, die BBCode SIZE-Tags von innen nach außen durch SPAN-HTML-Tags ersetzt. Beachten Sie, dass der unten stehende (schnelle) Regex komplex ist (zum einen implementiert er Jeffrey Friedls "Unrolling-the-Loop" -Effizienztechnik - siehe: Beherrschen regulärer Ausdrücke (3. Ausgabe) für Details), und IMO sollten alle komplexen regulären Ausdrücke sein gründlich kommentiert und zur besseren Lesbarkeit formatiert. Da Javascript keinen Freiraummodus hat, wird der folgende reguläre Ausdruck zunächst im PHP-Freiraummodus vollständig kommentiert dargestellt. Der tatsächlich verwendete unkommentierte js-Regex ist identisch mit dem ausführlich kommentierten.

Regex für die innersten (möglicherweise verschachtelten) SIZE-Tags:

// Regular expression in commented (PHP string) format.
$re = '% # Match innermost [size=ddd]...[/size] structure.
    \[size=            # Literal start tag name, =.
    (\d+)\]            # $1: Size number, ending-"]".
    (                  # $2: Element contents.
      # Use Friedls "Unrolling-the-Loop" technique:
      #   Begin: {normal* (special normal*)*} construct.
      [^[]*            # {normal*} Zero or more non-"[".
      (?:              # Begin {(special normal*)*}.
        \[             # {special} Tag open literal char,
        (?!            # but only if NOT start of
          size=\d+\]   # [size=ddd] open tag
        | \/size\]     # or [/size] close tag.
        )              # End negative lookahead.
        [^[]*          # More {normal*}.
      )*               # Finish {(special normal*)*}.
    )                  # $2: Element contents.
    \[\/size\]         # Literal end tag.
    %ix';

Javascript-Funktion: parseSizeBBCode(text)

function parseSizeBBCode(text) {
    // Here is the same regular expression in javascript syntax:
    var re = /\[size=(\d+)\]([^[]*(?:\[(?!size=\d+\]|\/size\])[^[]*)*)\[\/size\]/ig;
    while(text.search(re) !== -1) {
        text = text.replace(re, '<span style="font-size: $1pt">$2</span>');
    }
    return text;
}

Beispiel Eingabe:

r'''
[size=10] size 10 stuff
    [size=20] size 20 stuff
        [size=30] size 30 stuff [/size]
    [/size]
[/size]
'''

Beispielausgabe:

r'''
<span style="font-size: 10pt"> size 10 stuff
    <span style="font-size: 20pt"> size 20 stuff
        <span style="font-size: 30pt"> size 30 stuff </span>
    </span>
</span>
'''

Haftungsausschluss - Verwenden Sie diese Lösung nicht!

Beachten Sie, dass die Verwendung von Regex zum Parsen von BBCode mit Gefahren verbunden ist! (Es gibt viele "Fallstricke", die hier nicht erwähnt werden.) Viele würden sagen, dass es unmöglich ist. Ich würde jedoch stark widersprechen und hätte tatsächlich einen vollständigen BBCode-Parser (in PHP) geschrieben, der rekursive reguläre Ausdrücke verwendet und recht gut funktioniert (und schnell ist). Sie können es hier in Aktion sehen: Neuer 2011 FluxBB Parser (Beachten Sie, dass einige sehr komplexe Regexe , nichts für schwache Nerven).

Im Allgemeinen würde ich jedoch dringend davor warnen, BBCode mit Regex zu analysieren, es sei denn, Sie haben ein sehr tiefes und gründliches Verständnis der regulären Ausdrücke (was durch sorgfältiges Studium und Üben von Friedls Meisterwerk). Mit anderen Worten, wenn Sie kein Meister der Regex sind (d. H. Ein Regex Guru ), vermeiden Sie es, sie für andere als die trivialsten Anwendungen zu verwenden.

4
Community 23 Mai 2017 im 10:32

Sie müssen nach + einen nicht gierigen Ausdruck verwenden, der durch ? qualifiziert ist.

Demo

1
David Hedlund 17 Okt. 2012 im 14:33
var reg = /\[size=(\d{1,2})\]([\u0000-\uFFFF]+?)\[\/size\]/gi;
                                              ↑
                                    make it lazy (non-greedy)

Das ist das gleiche wie

var reg = /\[size=(\d{1,2})\](.+?)\[\/size\]/gi;
2
Ωmega 17 Okt. 2012 im 14:35