- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章js 玩转正则表达式之语法高亮由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
学了几天正则,差不多该总结整理写成果了,之前就想写语法高亮匹配来着,不过水平不够,看着例子都不理解.
那么我们来分析下两位大神 次碳酸钴 和 Barret Lee 语法高亮实现.
先说 Barret Lee 的这篇 《几个小例子教你如何实现正则表达式highlight高亮》 。
之前看的时候只觉的神奇,特别是下面那个一步一步分开匹配的例子,更是霸气测漏,不过作者也说了,分开只是为了演示方便,可以很直观的看到这一步匹配了什么,不然一步到位匹配完成,你都不知道发生了什么就处理完毕了。 来看下他的正则 。
。
。
小胡子哥可能是不想重复造轮子,只是想弄清楚如何造这样的轮子而已,所以他写这个东西点到即止,没有深入详细的处理,做的比较粗糙。 当然我也不是说他什么,只是简单评论一下而已,毕竟优秀的语法高亮插件多的是,没必要自己重复造,学习下原理即可.
我们再来分析下 次碳酸钴 这篇 《如何实现正则表达式的JavaScript的代码高亮》 其实这篇已经分析的非常详细了,我只能简单补充说明下。 次碳酸钴 思维一向比较严谨,这篇文章之前我看了一个多小时,只能看个大概,这次重新分析了一遍,然后自己实现了一遍,竟然也花去我半天时间, 不过非常值得,真心学到了很多.
先来看一下大体的逻辑吧.
。
。
原文对最后一个 [\S\s] 的描述:我们必须匹配到每一个字符。因为它们都需要做一次HTML转义。 然后下面有详细的代码.
这是一篇非常不错的文章,我前前后后至少看了不下10次了,前两天才差不多完全明白.
不过这个代码还有一些小小的瑕疵,比如字符串不能匹配折行那种,字符串匹配优化.
还有数字匹配不够全面只能匹配 0xff, 12.34, 1e3 这几类,如 .123 12.3e+3 等格式都无法匹配到。 还有关键词顺序我觉得可以稍微优化下。 因为 传统型NFA 引擎的只是从左往右匹配,匹配到了就停止下一个分支的操作。 所以把最常出现的关键词放前面,可以提升一部分性能。 最后,最好是 new RegExp 这样对于代码量大的代码性能上会有所提升.
下面就给出我的正则和简单的demo吧。(其实只是对 次碳酸钴 源码的优化而已。。) 先来看正则部分:
。
。
合并了布尔和空值一个分组,然后优化了正则分组,所以比他减少了2个分组。 他 2,3 是字符串分组,因为 (["']) 捕获了前面的引号,而我的正则没这么做。 这个 (true|false|null|undefined|NaN) 如果你不喜欢放在一个分组了,分开也行、 是不是同一个分组,只是为了区分着色而已。 sublime text 下 true|false|null|undefined|NaN 都是一个颜色,而 notepad++ 则只着色了 true|false ,我只想说 呵呵.
好了,差不多该给例子了。 我相信,不少人在看到这之前已经关掉了,或者只是拉了下滚动条然后关掉了。 不过我写这个就是为了给这些认真看下来的朋友,只要有一个人看,我觉得就不会白写了。 例子:
。
// 单行注释 /** * 多行注释 * @date 2014-05-12 22:24:37 * @name 测试一下 */ var str1 = "123\"456"; var str2 = '123\'456'; var str3 = "123\ 456",
。
var num = 123; var arr = [12, 12.34, .12, 1e3, 1e+3, 1e-3, 12.34e3, 12.34e+3, 12.34e-3, .1234e3]; var arr = ["12", "12.34", '.12, 1e3', '1e+3, 1e-3', '12.34e3, 12.34e+3, 12.34e-3', ".1234e3"]; var arr = [/12", "12.34/, /"12\/34"/],
for (var i=0; i<1e3; i++) { var node = document.getElementById("a"+i); arr.push(node); } 。
function test () { return true; } test(),
。
(function(window, undefined) { var _re_js = new RegExp('(\\/\\/.*|\\/\\*[\\s\\S]*?\\*\\/)|("(?:[^"\\\\]|\\\\[\\s\\S])*"|\'(?:[^\'\\\\]|\\\\[\\s\\S])*\')|\\b(true|false|null|undefined|NaN)\\b|\\b(var|for|if|else|return|this|while|new|function|switch|case|typeof|do|in|throw|try|catch|finally|with|instance|delete|void|break|continue)\\b|\\b(document|Date|Math|window|Object|location|navigator|Array|String|Number|Boolean|Function|RegExp)\\b|(?:[^\\W\\d]|\\$)[\\$\\w]*|(0[xX][0-9a-fA-F]+|\\d+(?:\\.\\d+)?(?:[eE][+-]?\\d+)?|\\.\\d+(?:[eE][+-]?\\d+)?)|(?:^|[^\\)\\]\\}])(\\/(?!\\*)(?:\\\\.|[^\\\\\\/\\n])+?\\/[gim]*)|[\\s\\S]', 'g'),
function prettify(node) { var code = node.innerHTML.replace(/\r\n|[\r\n]/g, "\n").replace(/^\s+|\s+$/g, ""); code = code.replace(_re_js, function() { var s, a = arguments; for (var i = 1; i <= 7; i++) { if (s = a[i]) { s = htmlEncode(s); switch (i) { case 1: //注释 com return '<span class="com">' + s + '</span>'; case 2: //字符串 str return '<span class="str">' + s + '</span>'; case 3: //true|false|null|undefined|NaN val return '<span class="val">' + s + '</span>'; case 4: //关键词 kwd return '<span class="kwd">' + s + '</span>'; case 5: //内置对象 obj return '<span class="obj">' + s + '</span>'; case 6: //数字 num return '<span class="num">' + s + '</span>'; case 7: //正则 reg return htmlEncode(a[0]).replace(s, '<span class="reg">' + s + '</span>'); } } } return htmlEncode(a[0]); }); code = code.replace(/(?:\s*\*\s*|(?: )*\*(?: )*)(@\w+)\b/g, ' * <span class="comkey">$1</span>') // 匹配注释中的标记 .replace(/(\w+)(\s*\(|(?: )*\()|(\w+)(\s*=\s*function|(?: )*=(?: )*function)/g, '<span class="func">$1</span>$2') // 匹配函数 return code; } 。
function htmlEncode(str) { var i, s = { //"&": /&/g, """: /"/g, "'": /'/g, "<": //g, "<br>": /\n/g, " ": / /g, " ": /\t/g }; for (i in s) { str = str.replace(s[i], i); } return str; } 。
window.prettify = prettify; })(window),
。
你们可以用下面的代码进行测试.
代码:
。
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <title>test</title> <style> /* 高亮样式 */ *{font-size:12px;} code{word-break:break-all;} 。
。
.com {color:#008000;} /* 注释 */ .comkey {color:#FFA500;} /* 注释标记 */ .str {color:#808080;} /* 字符串 */ .val {color:#000080;} /* true|false|null|undefined|NaN */ .kwd {color:#000080;font:bold 12px 'comic sans ms', sans-serif;} /* 关键词 */ .obj {color:#000080;} /* 内置对象 */ .num {color:#FF0000;} /* 数字 */ .reg {color:#8000FF;} /* 正则 */ .func {color:#A355B9;} /* 函数 */ </style> </head> <body> 。
<code id="regdemon"> // 单行注释 /** * 多行注释 * @date 2014-05-12 22:24:37 * @name 测试一下 */ var str1 = "123\"456"; var str2 = '123\'456'; var str3 = "123\ 456",
var num = 123; var arr = [12, 12.34, .12, 1e3, 1e+3, 1e-3, 12.34e3, 12.34e+3, 12.34e-3, .1234e3]; var arr = ["12", "12.34", '.12, 1e3', '1e+3, 1e-3', '12.34e3, 12.34e+3, 12.34e-3', ".1234e3"]; var arr = [/12", "12.34/, /"12\/34"/],
for (var i=0; i<1e3; i++) { var node = document.getElementById("a"+i); arr.push(node); } 。
function test () { return true; } test(),
。
(function(window, undefined) { var _re_js = new RegExp('(\\/\\/.*|\\/\\*[\\s\\S]*?\\*\\/)|("(?:[^"\\\\]|\\\\[\\s\\S])*"|\'(?:[^\'\\\\]|\\\\[\\s\\S])*\')|\\b(true|false|null|undefined|NaN)\\b|\\b(var|for|if|else|return|this|while|new|function|switch|case|typeof|do|in|throw|try|catch|finally|with|instance|delete|void|break|continue)\\b|\\b(document|Date|Math|window|Object|location|navigator|Array|String|Number|Boolean|Function|RegExp)\\b|(?:[^\\W\\d]|\\$)[\\$\\w]*|(0[xX][0-9a-fA-F]+|\\d+(?:\\.\\d+)?(?:[eE][+-]?\\d+)?|\\.\\d+(?:[eE][+-]?\\d+)?)|(?:^|[^\\)\\]\\}])(\\/(?!\\*)(?:\\\\.|[^\\\\\\/\\n])+?\\/[gim]*)|[\\s\\S]', 'g'),
function prettify(node) { var code = node.innerHTML.replace(/\r\n|[\r\n]/g, "\n").replace(/^\s+|\s+$/g, ""); code = code.replace(_re_js, function() { var s, a = arguments; for (var i = 1; i <= 7; i++) { if (s = a[i]) { s = htmlEncode(s); switch (i) { case 1: //注释 com return '<span class="com">' + s + '</span>'; case 2: //字符串 str return '<span class="str">' + s + '</span>'; case 3: //true|false|null|undefined|NaN val return '<span class="val">' + s + '</span>'; case 4: //关键词 kwd return '<span class="kwd">' + s + '</span>'; case 5: //内置对象 obj return '<span class="obj">' + s + '</span>'; case 6: //数字 num return '<span class="num">' + s + '</span>'; case 7: //正则 reg return htmlEncode(a[0]).replace(s, '<span class="reg">' + s + '</span>'); } } } return htmlEncode(a[0]); }); code = code.replace(/(?:\s*\*\s*|(?: )*\*(?: )*)(@\w+)\b/g, ' * <span class="comkey">$1</span>') // 匹配注释中的标记 .replace(/(\w+)(\s*\(|(?: )*\()|(\w+)(\s*=\s*function|(?: )*=(?: )*function)/g, '<span class="func">$1</span>$2') // 匹配函数 return code; } 。
function htmlEncode(str) { var i, s = { //"&": /&/g, """: /"/g, "'": /'/g, "<": /</g, ">": />/g, "<br>": /\n/g, " ": / /g, " ": /\t/g }; for (i in s) { str = str.replace(s[i], i); } return str; } 。
window.prettify = prettify; })(window); </code> 。
<script> (function(window, undefined) { var _re_js = new RegExp('(\\/\\/.*|\\/\\*[\\s\\S]*?\\*\\/)|("(?:[^"\\\\]|\\\\[\\s\\S])*"|\'(?:[^\'\\\\]|\\\\[\\s\\S])*\')|\\b(true|false|null|undefined|NaN)\\b|\\b(var|for|if|else|return|this|while|new|function|switch|case|typeof|do|in|throw|try|catch|finally|with|instance|delete|void|break|continue)\\b|\\b(document|Date|Math|window|Object|location|navigator|Array|String|Number|Boolean|Function|RegExp)\\b|(?:[^\\W\\d]|\\$)[\\$\\w]*|(0[xX][0-9a-fA-F]+|\\d+(?:\\.\\d+)?(?:[eE][+-]?\\d+)?|\\.\\d+(?:[eE][+-]?\\d+)?)|(?:^|[^\\)\\]\\}])(\\/(?!\\*)(?:\\\\.|[^\\\\\\/\\n])+?\\/[gim]*)|[\\s\\S]', 'g'),
function prettify(node) { var code = node.innerHTML.replace(/\r\n|[\r\n]/g, "\n").replace(/^\s+|\s+$/g, ""); code = code.replace(_re_js, function() { var s, a = arguments; for (var i = 1; i <= 7; i++) { if (s = a[i]) { s = htmlEncode(s); switch (i) { case 1: //注释 com return '<span class="com">' + s + '</span>'; case 2: //字符串 str return '<span class="str">' + s + '</span>'; case 3: //true|false|null|undefined|NaN val return '<span class="val">' + s + '</span>'; case 4: //关键词 kwd return '<span class="kwd">' + s + '</span>'; case 5: //内置对象 obj return '<span class="obj">' + s + '</span>'; case 6: //数字 num return '<span class="num">' + s + '</span>'; case 7: //正则 reg return htmlEncode(a[0]).replace(s, '<span class="reg">' + s + '</span>'); } } } return htmlEncode(a[0]); }); code = code.replace(/(?:\s*\*\s*|(?: )*\*(?: )*)(@\w+)\b/g, ' * <span class="comkey">$1</span>') // 匹配注释中的标记 .replace(/(\w+)(\s*\(|(?: )*\()|(\w+)(\s*=\s*function|(?: )*=(?: )*function)/g, '<span class="func">$1</span>$2') // 匹配函数 return code; } 。
function htmlEncode(str) { var i, s = { //"&": /&/g, """: /"/g, "'": /'/g, "<": /</g, ">": />/g, "<br>": /\n/g, " ": / /g, " ": /\t/g }; for (i in s) { str = str.replace(s[i], i); } return str; } 。
window.prettify = prettify; })(window),
var code = document.getElementById("regdemon"); code.innerHTML = prettify(code); </script> </body> </html> 。
。
差不多结合了 小胡子哥 和 次碳酸钴 两个思路的结果,现在比较完善了。 兼容性什么的还没测试,也没必要测试了,我也没打算自己写各种语法的高亮,太TM累了。.
最后此篇关于js 玩转正则表达式之语法高亮的文章就讲到这里了,如果你想了解更多关于js 玩转正则表达式之语法高亮的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我正在用 yacc/bison 编写一个简单的计算器。 表达式的语法看起来有点像这样: expr : NUM | expr '+' expr { $$ = $1 + $3; } | expr '-'
我开始学习 lambda 表达式,并在以下情况下遇到了以下语句: interface MyNumber { double getValue(); } MyNumber number; nu
这两个 Linq 查询有什么区别: var result = ResultLists().Where( c=> c.code == "abc").FirstOrDefault(); // vs. va
如果我们查看 draft C++ standard 5.1.2 Lambda 表达式 段 2 说(强调我的 future ): The evaluation of a lambda-expressio
我使用的是 Mule 4.2.2 运行时、studio 7.5.1 和 Oracle JDK 1.8.0_251。 我在 java 代码中使用 Lambda 表达式,该表达式由 java Invoke
我是 XPath 的新手。我有网页的html源 http://london.craigslist.co.uk/com/1233708939.html 现在我想从上面的页面中提取以下数据 完整日期 电子
已关闭。这个问题是 off-topic 。目前不接受答案。 想要改进这个问题吗? Update the question所以它是on-topic用于堆栈溢出。 已关闭10 年前。 Improve th
我将如何编写一个 Cron 表达式以在每天上午 8 点和下午 3:30 触发?我了解如何创建每天触发一次的表达式,而不是在多个设定时间触发。提前致谢 最佳答案 你应该只使用两行。 0 8 * * *
这个问题已经有答案了: What do 3 dots next to a parameter type mean in Java? (9 个回答) varargs and the '...' argu
我是 python 新手,在阅读 BeautifulSoup 教程时,我不明白这个表达式“[x for x in titles if x.findChildren()][:-1]”我不明白?你能解释一
(?:) 这是一个有效的 ruby 正则表达式,谁能告诉我它是什么意思? 谢谢 最佳答案 正如其他人所说,它被用作正则表达式的非捕获语法,但是,它也是正则表达式之外的有效 ruby 语法。 在
这个问题在这里已经有了答案: Why does ++[[]][+[]]+[+[]] return the string "10"? (10 个答案) 关闭 8 年前。 谁能帮我处理这个 JavaSc
这个问题在这里已经有了答案: What is the "-->" operator in C++? (29 个答案) Java: Prefix/postfix of increment/decrem
这个问题在这里已经有了答案: List comprehension vs. lambda + filter (16 个答案) 关闭 10 个月前。 我不确定我是否需要 lambda 或其他东西。但是,
C 中的 assert() 函数工作原理对我来说就像一片黑暗的森林。根据这里的答案https://stackoverflow.com/a/1571360 ,您可以使用以下构造将自定义消息输出到您的断言
在this页,John Barnes 写道: If the conditional expression is the argument of a type conversion then effec
我必须创建一个调度程序,它必须每周从第一天上午 9 点到第二天晚上 11 点 59 分运行 2 天(星期四和星期五)。为此,我需要提供一个 cron 表达式。 0-0 0-0 9-23 ? * THU
我正在尝试编写一个 Linq 表达式来检查派生类中的属性,但该列表由来自基类的成员组成。下面的示例代码。以“var list”开头的 Process 方法的第二行无法编译,但我不确定应该使用什么语法来
此 sed 表达式将输入字符串转换为两行输出字符串。两条输出行中的每一行都由输入的子串组成。第一行需要转换成大写: s:random_stuff\(choice1\|choice2\){\([^}]*
我正在使用 Quartz.Net 在我的应用程序中安排我的工作。我只是想知道是否可以为以下场景构建 CRON 表达式: Every second between 2:15AM and 5:20AM 最
我是一名优秀的程序员,十分优秀!