javascript中的BB-Code-RegEx [英] BB-Code-RegEx in javascript

查看:232
本文介绍了javascript中的BB-Code-RegEx的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这段代码:

  var s_1 ='blabla [size = 42]答案[/ size] bla bla blupblub'; 
var s_2 ='blabla [size = 42]答案[/ size] bla bla blupblub [size = 32] 32 [/ size]';

alert('测试字符串:\ n'+ s_1 +'\ n \ n替换:\ n'+ size(s_1));
alert('Test-String:\ n'+ s_2 +'\ n \ n替换:\ n'+ size(s_2));


函数大小{
var reg = / \ [size =(\d {1,2})\]([\ 000000 \\\￿] +)\ [\ / size\] / GI;
s = s.replace(reg,function(match,p1,p2){
return'< span style =font-size:'+((parseInt(p1)> 48)?' 48':p1)+'px;>'+ p2 +'< / span>';
})
返回s;
}

它应该替换所有出现的[size = nn] [/大小] - 标签但它只取代了外面的标签。我无法弄清楚如何更换所有这些。 (请不要建议使用PHP脚本,我想要为BB-Code格式化文本进行实时预览)



测试它

解决方案

匹配(可能是嵌套的)BBCode标记



如果元素是嵌套的,则需要多遍方法。这可以通过两种方式之一完成;从内到外匹配(不需要递归表达式),或从外部匹配(需要递归表达式)。 (另请参阅我对类似问题的回答: PHP,preg_replace中的嵌套模板)但是,因为Javascript正则表达式引擎没有支持递归表达式,使用正则表达式(正确)执行此操作的唯一方法是从内到外。下面是一个经过测试的函数,它从内到外用SPAN html标签替换BBCode SIZE标签。请注意,下面的(快速)正则表达式很复杂(一方面它实现了Jeffrey Friedl的展开循环效率技术 - 请参阅:掌握正则表达式(第3版)以获取详细信息),以及IMO应该对所有复杂的正则表达式进行全面评论和格式化以便于阅读。由于Javascript没有自由间隔模式,下面的正则表达式首先在PHP自由间隔模式下完全注释。实际使用的未注释的js正则表达式与详细注释的相同。



正则表达式匹配最内部(可能是嵌套的)SIZE标记:



  //注释(PHP字符串)格式的正则表达式。 
$ re ='%#匹配最里面的[size = ddd] ... [/ size]结构。
\ [size =#Literal开始标记名称,=。
(\d +)\]#$ 1:大小编号,结尾 - ]。
(#$ 2:元素内容。
#使用FriedlsUnrolling-the-Loop技术:
#Begin:{normal *(special normal *)*} construct。
[^ [] *#{normal *}零或更多非 - [。
(?:#Begin {(special normal *)*}。
\ [#{special}标签打开文字字符,
(?!#但仅限于
尺寸的开头= \d + \]#[size = ddd]打开标签
| \ / size \]#或者[/ size]关闭标签。
)#End negative negative lookahead。
[^ [] *#More {normal *}。
)* #Finite {(special normal *)*} 。
)#$ 2:元素内容。
\ [\ / size\] #Literal结束标记。
%ix';



Javascript函数: parseSizeBBCode(text)



  function parseSizeBBCode(text){
//这里是javascript中的相同正则表达式语法:
var re = / \ [size =(\d +)\]([^ [] *(?:\ [(?!size = \d + \] | \ / size\])[^ [] *)*)\ [\ / size\] / IG;
while(text.search(re)!== -1){
text = text.replace(re,'< span style =font-size:$ 1pt> $ 2< /跨度>');
}
返回文字;
}



输入示例:



< pre class =lang-py prettyprint-override> r'''
[size = 10] size 10 stuff
[size = 20] size 20 stuff
[size = 30]尺码30件[/尺寸]
[/尺寸]
[/尺寸]
'''



示例输出:



  r' ''
< span style =font-size:10pt>大小10个东西
< span style =font-size:20pt>大小20个东西
< span style =font-size:30pt>尺码30件< / span>
< / span>
< / span>
'''



免责声明 - 请勿使用此解决方案!



请注意,使用正则表达式解析BBCode充满了危险! (这里没有提到很多陷阱。)很多人会说它不可能。但是,我强烈反对并且事实上已经编写了一个完整的BBCode解析器(在PHP中),它使用递归正则表达式并且工作得非常好(并且快速)。你可以在这里看到它: 2011年新版FluxBB解析器(注意它使用了一些< a href =http://jmrware.com/articles/2011/fluxbb_jmr_dev/viewtopic.php?id=3 =nofollow noreferrer>非常复杂的正则表达式不适合胆小的人。)



但总的来说,我强烈警告不要使用正则表达式解析BBCode,除非你对正则表达式有一个非常深入和透彻的理解(可以通过仔细研究和实践< a href =https://rads.stackoverflow.com/amzn/click/com/0596528124 =nofollow noreferrer =nofollow noreferrertitle =放下我读过的最有用的书>弗里德尔的杰作)。换句话说,如果你不是正则表达式的主人(即正则表达式 guru ),那么除了最简单的应用之外,不要使用它们。


I have this piece of 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;    
}

It's supposed to replace all occurrences of the "[size=nn][/size]"-Tags but it only replaces the outer ones. I can't figure out how to replace all of them. (Please don't recommend to use a PHP-Script, I'd like to have a live-preview for the BB-Code formated Text)

Test it

解决方案

Matching (possibly nested) BBCode tags

A multi-pass approach is required if the elements are nested. This can be accomplished in one of two ways; matching from the inside out (no recursive expression required), or from the outside in (which requires a recursive expression). (See also my answer to a similar question: PHP, nested templates in preg_replace) However, since the Javascript regex engine does not support recursive expressions, the only way to (correctly) do this using regex is from the inside out. Below is a tested function which replaces BBCode SIZE tags with SPAN html tags from the inside out. Note that the (fast) regex below is complex (for one thing it implements Jeffrey Friedl's "unrolling-the-loop" efficiency technique - See: Mastering Regular Expressions (3rd Edition) for details), and IMO all complex regexes should be thoroughly commented and formatted for readability. Since Javascript has no free-spacing mode, the regex below is first presented fully commented in PHP free-spacing mode. The uncommented js regex actually used is identical to the verbose commented one.

Regex to match innermost of (possibly nested) 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 function: 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;
}

Example input:

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

Example output:

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>
'''

Disclaimer - Don't use this solution!

Note that using regex to parse BBCode is fraught with peril! (There are a lot of "gotchas" not mentioned here.) Many would say that it is impossible. However, I would strongly disagree and have in fact written a complete BBCode parser (in PHP) which uses recursive regular expressions and works quite nicely (and is fast). You can see it in action here: New 2011 FluxBB Parser (Note that it uses some very complex regexes not for the faint of heart).

But in general, I would strongly warn against parsing BBCode using regex unless you have a very deep and thorough understanding of regular expressions (which can be gained from careful study and practice of Friedl's masterpiece). In other words, if you are not a master of regex (i.e. a regex guru), steer clear from using them for any but the most trivial of applications.

这篇关于javascript中的BB-Code-RegEx的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆