在 Javascript 中解析 BBCode
Parsing BBCode in Javascript
我正在使用这个 (http://coursesweb.net/javascript/convert-bbcode-html-javascript_cs) 作为我解析 BBCode 的脚本。我已经扩展了它可以处理的 BBCodes,但是当换行符紧跟在开始标记之后时,我遇到了一个问题,例如
[code]
code....
[/code]
代码为'inline'则不会出现该问题
[code]code....
[/code]`
用于匹配这些标签内内容的正则表达式是 (.*?)
,我知道它不匹配换行符。我试过 ([^\r\n])
来匹配换行符,但这也没有用。
我认为这是一个简单的问题,但我对正则表达式没有什么经验,因此我们将不胜感激
编辑:这是我正在使用的正则表达式的完整列表
var tokens = {
'URL' : '((?:(?:[a-z][a-z\d+\-.]*:\/{2}(?:(?:[a-z0-9\-._~\!$&\'*+,;=:@|]+|%[\dA-F]{2})+|[0-9.]+|\[[a-z0-9.]+:[a-z0-9.]+:[a-z0-9.:]+\])(?::\d*)?(?:\/(?:[a-z0-9\-._~\!$&\'*+,;=:@|]+|%[\dA-F]{2})*)*(?:\?(?:[a-z0-9\-._~\!$&\'*+,;=:@\/?|]+|%[\dA-F]{2})*)?(?:#(?:[a-z0-9\-._~\!$&\'*+,;=:@\/?|]+|%[\dA-F]{2})*)?)|(?:www\.(?:[a-z0-9\-._~\!$&\'*+,;=:@|]+|%[\dA-F]{2})+(?::\d*)?(?:\/(?:[a-z0-9\-._~\!$&\'*+,;=:@|]+|%[\dA-F]{2})*)*(?:\?(?:[a-z0-9\-._~\!$&\'*+,;=:@\/?|]+|%[\dA-F]{2})*)?(?:#(?:[a-z0-9\-._~\!$&\'*+,;=:@\/?|]+|%[\dA-F]{2})*)?)))',
'LINK' : '([a-z0-9\-\./]+[^"\' ]*)',
'EMAIL' : '((?:[\w\!\#$\%\&\'\*\+\-\/\=\?\^\`{\|\}\~]+\.)*(?:[\w\!\#$\%\'\*\+\-\/\=\?\^\`{\|\}\~]|&)+@(?:(?:(?:(?:(?:[a-z0-9]{1}[a-z0-9\-]{0,62}[a-z0-9]{1})|[a-z])\.)+[a-z]{2,6})|(?:\d{1,3}\.){3}\d{1,3}(?:\:\d{1,5})?))',
'TEXT' : '(.*?)',
'SIMPLETEXT' : '([a-zA-Z0-9-+.,_ ]+)',
'INTTEXT' : '([a-zA-Z0-9-+,_. ]+)',
'IDENTIFIER' : '([a-zA-Z0-9-_]+)',
'COLOR' : '([a-z]+|#[0-9abcdef]+)',
'NUMBER' : '([0-9]+)',
'ALL' : '([^\r\n])',
};
编辑 2:用于匹配的完整 JS
var token_match = /{[A-Z_]+[0-9]*}/ig;
var _getRegEx = function(str) {
var matches = str.match(token_match);
var nrmatches = matches.length;
var i = 0;
var replacement = '';
if (nrmatches <= 0) {
return new RegExp(preg_quote(str), 'g'); // no tokens so return the escaped string
}
for(; i < nrmatches; i += 1) {
// Remove {, } and numbers from the token so it can match the
// keys in tokens
var token = matches[i].replace(/[{}0-9]/g, '');
if (tokens[token]) {
// Escape everything before the token
replacement += preg_quote(str.substr(0, str.indexOf(matches[i]))) + tokens[token];
// Remove everything before the end of the token so it can be used
// with the next token. Doing this so that parts can be escaped
str = str.substr(str.indexOf(matches[i]) + matches[i].length);
}
}
replacement += preg_quote(str);
return new RegExp(replacement, 'gi');
};
var _getTpls = function(str) {
var matches = str.match(token_match);
var nrmatches = matches.length;
var i = 0;
var replacement = '';
var positions = {};
var next_position = 0;
if (nrmatches <= 0) {
return str; // no tokens so return the string
}
for(; i < nrmatches; i += 1) {
// Remove {, } and numbers from the token so it can match the
// keys in tokens
var token = matches[i].replace(/[{}0-9]/g, '');
var position;
// figure out what $# to use (, )
if (positions[matches[i]]) {
position = positions[matches[i]];
} else {
// token doesn't have a position so increment the next position
// and record this token's position
next_position += 1;
position = next_position;
positions[matches[i]] = position;
}
if (tokens[token]) {
replacement += str.substr(0, str.indexOf(matches[i])) + '$' + position;
str = str.substr(str.indexOf(matches[i]) + matches[i].length);
}
}
replacement += str;
return replacement;
};
JavaScript 不处理 multi-line 正则表达式匹配。相反,您必须使用 this SO answer 中描述的 [\s\S]
技巧。也许?
/\[code\][\s\S]*\[code\]/
此外,RegExps 可能不是解析语法的最佳选择。它非常复杂。我建议解析字符串并构建抽象语法树,然后从中呈现 HTML。
这对我有用:(也更新了这个以避免混淆)
\[code\]([\s\S]*?)\[\/code\]
请参阅 regexpal 并输入以下内容:
[code]
code....
[/code]
[code]code.... [/code]
更新:
将正则表达式修复为以下内容,这对我来说在 Chrome 控制台中有效:
/\[code\]([\s\S]*?)\[\/code\]/g.exec("[code]hello world \n[/code]")
我正在使用这个 (http://coursesweb.net/javascript/convert-bbcode-html-javascript_cs) 作为我解析 BBCode 的脚本。我已经扩展了它可以处理的 BBCodes,但是当换行符紧跟在开始标记之后时,我遇到了一个问题,例如
[code]
code....
[/code]
代码为'inline'则不会出现该问题
[code]code....
[/code]`
用于匹配这些标签内内容的正则表达式是 (.*?)
,我知道它不匹配换行符。我试过 ([^\r\n])
来匹配换行符,但这也没有用。
我认为这是一个简单的问题,但我对正则表达式没有什么经验,因此我们将不胜感激
编辑:这是我正在使用的正则表达式的完整列表
var tokens = {
'URL' : '((?:(?:[a-z][a-z\d+\-.]*:\/{2}(?:(?:[a-z0-9\-._~\!$&\'*+,;=:@|]+|%[\dA-F]{2})+|[0-9.]+|\[[a-z0-9.]+:[a-z0-9.]+:[a-z0-9.:]+\])(?::\d*)?(?:\/(?:[a-z0-9\-._~\!$&\'*+,;=:@|]+|%[\dA-F]{2})*)*(?:\?(?:[a-z0-9\-._~\!$&\'*+,;=:@\/?|]+|%[\dA-F]{2})*)?(?:#(?:[a-z0-9\-._~\!$&\'*+,;=:@\/?|]+|%[\dA-F]{2})*)?)|(?:www\.(?:[a-z0-9\-._~\!$&\'*+,;=:@|]+|%[\dA-F]{2})+(?::\d*)?(?:\/(?:[a-z0-9\-._~\!$&\'*+,;=:@|]+|%[\dA-F]{2})*)*(?:\?(?:[a-z0-9\-._~\!$&\'*+,;=:@\/?|]+|%[\dA-F]{2})*)?(?:#(?:[a-z0-9\-._~\!$&\'*+,;=:@\/?|]+|%[\dA-F]{2})*)?)))',
'LINK' : '([a-z0-9\-\./]+[^"\' ]*)',
'EMAIL' : '((?:[\w\!\#$\%\&\'\*\+\-\/\=\?\^\`{\|\}\~]+\.)*(?:[\w\!\#$\%\'\*\+\-\/\=\?\^\`{\|\}\~]|&)+@(?:(?:(?:(?:(?:[a-z0-9]{1}[a-z0-9\-]{0,62}[a-z0-9]{1})|[a-z])\.)+[a-z]{2,6})|(?:\d{1,3}\.){3}\d{1,3}(?:\:\d{1,5})?))',
'TEXT' : '(.*?)',
'SIMPLETEXT' : '([a-zA-Z0-9-+.,_ ]+)',
'INTTEXT' : '([a-zA-Z0-9-+,_. ]+)',
'IDENTIFIER' : '([a-zA-Z0-9-_]+)',
'COLOR' : '([a-z]+|#[0-9abcdef]+)',
'NUMBER' : '([0-9]+)',
'ALL' : '([^\r\n])',
};
编辑 2:用于匹配的完整 JS
var token_match = /{[A-Z_]+[0-9]*}/ig;
var _getRegEx = function(str) {
var matches = str.match(token_match);
var nrmatches = matches.length;
var i = 0;
var replacement = '';
if (nrmatches <= 0) {
return new RegExp(preg_quote(str), 'g'); // no tokens so return the escaped string
}
for(; i < nrmatches; i += 1) {
// Remove {, } and numbers from the token so it can match the
// keys in tokens
var token = matches[i].replace(/[{}0-9]/g, '');
if (tokens[token]) {
// Escape everything before the token
replacement += preg_quote(str.substr(0, str.indexOf(matches[i]))) + tokens[token];
// Remove everything before the end of the token so it can be used
// with the next token. Doing this so that parts can be escaped
str = str.substr(str.indexOf(matches[i]) + matches[i].length);
}
}
replacement += preg_quote(str);
return new RegExp(replacement, 'gi');
};
var _getTpls = function(str) {
var matches = str.match(token_match);
var nrmatches = matches.length;
var i = 0;
var replacement = '';
var positions = {};
var next_position = 0;
if (nrmatches <= 0) {
return str; // no tokens so return the string
}
for(; i < nrmatches; i += 1) {
// Remove {, } and numbers from the token so it can match the
// keys in tokens
var token = matches[i].replace(/[{}0-9]/g, '');
var position;
// figure out what $# to use (, )
if (positions[matches[i]]) {
position = positions[matches[i]];
} else {
// token doesn't have a position so increment the next position
// and record this token's position
next_position += 1;
position = next_position;
positions[matches[i]] = position;
}
if (tokens[token]) {
replacement += str.substr(0, str.indexOf(matches[i])) + '$' + position;
str = str.substr(str.indexOf(matches[i]) + matches[i].length);
}
}
replacement += str;
return replacement;
};
JavaScript 不处理 multi-line 正则表达式匹配。相反,您必须使用 this SO answer 中描述的 [\s\S]
技巧。也许?
/\[code\][\s\S]*\[code\]/
此外,RegExps 可能不是解析语法的最佳选择。它非常复杂。我建议解析字符串并构建抽象语法树,然后从中呈现 HTML。
这对我有用:(也更新了这个以避免混淆)
\[code\]([\s\S]*?)\[\/code\]
请参阅 regexpal 并输入以下内容:
[code]
code....
[/code]
[code]code.... [/code]
更新: 将正则表达式修复为以下内容,这对我来说在 Chrome 控制台中有效:
/\[code\]([\s\S]*?)\[\/code\]/g.exec("[code]hello world \n[/code]")