原文地址:www.zhangxinxu.com/wordpress/2…css
就是写一个检验方法,输出不符合排版规则的内容。html
翻译规则地址:译文排版规则指南前端
补充细节:git
对于字符内容的格式验证,天然就是正则表达式了,所以,本期的题目主要目的之一是学习正则表达式。程序员
正则表达式规则在全部的语言中都是通用的,除了细节上上有些差别,须要的是如出一辙的,因此学会了JS中的正则表达式,其余开发语言也能够受用,包括CSS这么语言(CSS中也有正则表达式)。github
JS这么语言要想基础扎实,正则表达式必定要好好学习,学到滴水不漏,能够极大提高处理本身的开发效率。包括在其余一些场合解放生产力,比方说Sublime Text这种编辑器在替换的时候是支持正则表达式的,若是你会正则表达式,则简单几个字符就能完成复杂替换,并且毫不会遗漏。那种解放生产力的感受,会让你以为,会代码真的好棒,好high!感受人生已经达到了高潮。正则表达式
CSS题目收到近50份回答,此次的正则小测,只有4个实现,人虽少,但都是精英。express
其中第一位@XboxYan的回答几乎直接大结局,我就以这我的回答做为案例讲讲正则表达式相关的一些东西。bash
/([\u4e00-\u9fa5]+[A-Za-z]+|[A-Za-z]+[\u4e00-\u9fa5]+)/g复制代码
JS中正则表达式书写有两种方式,一种是直接两个斜杠,还有一种是使用RegExp对象构建。微信
上面这个例子啊,就是使用的斜杠。
举个最简单的例子,/1/
能够匹配字符串里面是否有字符'1'
。
咱们分解下这个正则表达式:
[\u4e00-\u9fa5]
表示中文字符匹配;[A-Za-z]
表示所有的英文字母。因而这个正则表达式能够理解为:
/(中文+英文+|英文+中文+)/g复制代码
是否是要更好理解了,剩下的一些符合是什么意思呢?
括号()
表示分组,这里能够去掉,浪费,白白占用匹配资源,直接下面这样既可:
/中文+英文+|英文+中文+/g复制代码
这里的竖着的管道符|
在正则表达式中表示或者的意思,也就是匹配中文后面直接跟着英文,或者英文后面直接带着中文这两个场景。
加号+
表示数量,表示1个或多个。正则表达式中还有其余一些表示数量的方法,例如:
+
表示1个或多个。?
表示1个或0个。*
表示任意数量。{}
能够指定数量,例如{2}
表示2个,{2, 6}
表示2-6个,{2,}
表示2个或2个以上。在本例中,加号也是能够去掉的,不影响匹配。所以,此正则能够进一步简化:
/中文英文|英文中文/g复制代码
也就是:
/[\u4e00-\u9fa5][A-Za-z]|[A-Za-z][\u4e00-\u9fa5]/g复制代码
斜杠后面的g
表示全局匹配,除了g
,还有i
和m
。其中i
表示不区分大小写,m
表示支持多行匹配。
所以,这里的正则能够进一步简化:
/[\u4e00-\u9fa5][a-z]|[a-z][\u4e00-\u9fa5]/gi复制代码
/([\u4e00-\u9fa5]+\d+|\d+[\u4e00-\u9fa5]+)/g复制代码
和第一个验证,中文和英文之间加空格相似,括号和加号均可以简化掉:
/[\u4e00-\u9fa5]\d|\d[\u4e00-\u9fa5]/g复制代码
而后这里有个\d
,表示的是匹配数字0-9
,这里的正则也能够写成下面这样:
/[\u4e00-\u9fa5][0-9]|[0-9][\u4e00-\u9fa5]/g复制代码
正则表达式中有不少指代专属类别字符的写法,例如:
\d
表示的是匹配数字;换成大写的\D
则表示匹配数字之外其余字符,等同于[^0-9]
。咱们若是想要匹配任意字符,可使用[\d\D]
这种写法。\w
表示匹配数字、字母和下划线;\W
表示匹配数字、字母和下划线觉得的其余字符。\s
表示匹配空格、制表符和换行符;换成大写的\S
则表示除了之外空格、制表符和换行符其余字符。\n
表示换行。/\d[A-Za-z]+/g复制代码
题目这个需求是不合理的,有些数字和单位之间是不能加空格的,有趣技术文章翻译,一定包含大量的代码,例如10px
等,显然不能加空格。所以,能够认为数字和大写字母之间须要空格。
所以,正则能够调整为:
/\d[A-Z]+/g复制代码
/([\s\S]{2}[\!|\·|\【|\】|\「|\」|\;|\:|\“|\”|\,|\《|\。|\》|\、|\?]\s+)|[\s+(\!|\·|\【|\】|\「|\」|\;|\:|\“|\”|\,|\《|\。|\》|\、|\?)[\s\S]{2}]/g复制代码
这个就至关长了,不少人看了会以为是天书同样,其实很简单,也有很多优化和改进空间。
首先,先后的[\s\S]{2}
是多余的,能够删掉,没有必要再额外匹配任意两个字符;
而后,最外面的分组括号()
也是多余的;
最后,全角符号在正则表达式中是没有必要使用反斜杠\
进行转义的,所以\【|\】|\「|\」|\;|\:
能够写做【|】|「|」|;|:
,这样阅读更方便些。
当前,这里最好的表示方法仍是使用RegExp对象,能够大大简化咱们的正则表达式,同时更利于维护。以下:
// 全角标点字符们
var strPunct = '!()【】『』「」《》“”‘’;:,。?、';
// 使用管道符链接
var regPunct = strPunct.split('').join('|');
// 此时的正则表达式
new RegExp('['+ regPunct +'] +| +['+ regPunct +']', 'g');复制代码
对吧,是否是简单也易读多了。
其中,空格我直接用的普通空格字符进行匹配的,而不是\s
,由于,我不想把换行符也过滤掉。
当咱们的正则表达式内容包含变量的时候,能够借助new RegExp()
来实现。
这里的标点指中文标点,由于英文标点不重复,有些不切实际,例如空字符串''
,就是合法的重复标点。
本来的实现:
/(\~|\`|\!|\[|\]|\{|\}|\;|\:|\"|\'|\,|\<|\.|\>|\/|\?|\!|\·|\【|\】\「\」|\;|\:|\“|\”|\,|\《|\。|\》|\、|\?)\1+/g复制代码
洋洋洒洒好长,咱们能够简化下:
new RegExp(`(${regPunct})\\1+`, 'g')复制代码
就是不使用重复中文标点了。其中,这里的\1
有必要好好说下。
\1
表示捕获匹配,表示捕获第一个分组括号中匹配的值,你能够理解为代称。在正则表达式中,每个分组括号()
都自带一个看不见的序号,从前日后依次是分组一,分组二,分组三……
这里的\1
就表示匹配的第一个标点,后面跟了个+
则表示,这里重复标点2个或多个都匹配。
捕获分组不只存在于正则表达式中,当咱们使用replace
方法进行正则替换的时候,也存在与替换方法中,使用美圆符号$
外加数字表示,例如先后空格过滤trim()
方法的简易polyfill:
if (!''.trim) {
String.prototype.trim = function () {
// $1表示第一个()中匹配的值
return this.replace(/^\s*(.*?)\s*$/, '$1');
};
}复制代码
其中'$1'
并非替换成字符串$1
意思,而是替换成第一个()
中匹配的值,在这里表示首尾空格之外的值。
若是咱们须要对捕获分组内容进行额外处理,能够把第二个参数做为function
处理,例如:
this.replace(/^\s*(.*?)\s*$/, function (matches, $1) {
// matches表示完整匹配内容(包括先后空格)
// $1则表示第一个()中匹配的值
// 此时就能够对$1进行处理,返回咱们须要的值
})复制代码
这个超easy:
/(\S(——)|(——)\S)/g复制代码
这里几个括号都是多余的,直接下面这样既可:
/\S——|——\S/g复制代码
/([^A-Za-z][\~|\`|\!|\[|\]|\{|\}|\;|\:|\"|\'|\,|\<|\.|\>|\/|\?][^A-Za-z])/g复制代码
实际匹配要比这个复杂,由于这个和最后一个应为整句须要使用半角标点大量冲突。因此这里规则要细化,先后至少须要出现中文,半角标点才转换为全角,不然认为是英文整句,不处理,保持忽略。
因而,我通过修改变成下面这样:
var strPunctHalf = '!()[]"\';:,.?'; // 不一样于全角字符,半角字符须要加转义 var regPunctHalf = strPunctHalf.split('').join('|\\'); // 此时的正则表达式 new RegExp(`[\u4e00-\u9fa5][a-z]*( *[${regPunctHalf}] *)|( *[${regPunctHalf}] *)[a-z]*[\u4e00-\u9fa5]`, 'gi');复制代码
也就是须要匹配10个全角数字,松松的,没什么好说。
/[\uFF10-\uFF19]+/g复制代码
/(\「[A-Za-z\s\~|\`|\!|\;|\:|\"|\'|\,|\<|\.|\>|\/|\?]*[\!|\·|\;|\:|\“|\”|\,\。|\、|\?][^\」]*\」)|(\《[A-Za-z\s\~|\`|\!|\;|\:|\"|\'|\,|\<|\.|\>|\/|\?]*[\!|\·|\;|\:|\“|\”|\,\。|\、|\?][^\》]*\》)/g复制代码
完整的英文整句的重要特征是单词与空格,考虑到标点以后可能会有空格,因而,优化了下:
new RegExp(`([a-z]+[${regPunct}|\\s])+[a-z]*([${regPunct}|\\s][a-z]+)+`, 'gi')复制代码
足以如今知足大多数的场景。
如今咱们有了基础技术,但还不足以做为工具,做为产品让更多人使用,由于在控制台输出这种事情非程序员之外的人是作不来的。
因此,能够将其变成可视化工具。
最后一个回答者@wingmeng参照了 @XboxYan 的一些思路除了输出验证结果,还输出了处理后的正确排版。
因而,站在这两位的肩膀上,我熬夜搞出了一个“翻译内容格式检验工具” —— check.html
直接输入内容,就能够高亮标记错误的翻译排版,同时显示正确的结果。
能够大大减轻校对时候的工做量,若是你也有参加掘金的翻译计划,或者本身平时翻译文章什么的,这个小工具能够试一试,虽不能100%完美解决各类排版问题,但至少能够解决大部分的问题,很是划算。
回到题目以外,在实际项目中遇到这样的排版验证需求,本质上就是用工程化的手段让普通人也能发现一些翻译排版的问题,所以,实际上,就算你正则表达式很是的烂,甚至一点也不会,你也能弄出一个可使用的工具来解放生产力。
首先经过交互设计手段来下降咱们实现的成本:
而后,判断什么类型的字符,能够不用走高大上、学习成本较高的正则表达式,能够试试基于charCode值判断,例如:
// 判断字符类型
String.prototype.kind = function () {
if (strPunct.indexOf(this) != -1) {
return 'punct';
}
var code = this.charCodeAt(0);
if (code >= 65296 && code <= 65305) {
return 'num-full';
}
if (code > 256) {
return 'zh';
}
if (code >= 48 && code <= 57) {
return 'num';
} else if (code >= 65 && code <= 90) {
return 'en-up';
} else if (code >= 97 && code <= 133) {
return 'en-low';
}
return 'unknown';
};复制代码
这个要好理解的多,不一样类型的字符串是有着特定的charCode区间范围的。
接下来事件就很简单了,咱们只要遍历须要检测的文本内容,判断一下当前字符和下一个字符是否不符合要求就能够了。比方说“中英文之间须要增长空格”,遍历的时候,若是当前字符是中文,同时上一个字符和或者下一个字母是英文,则返回并高亮标记。
验证就结束了,一个循环+字符判断,就算只学习一个月的JavaScript也可以实现,这就是“傻白甜”实现方式。
眼见为实,为了方便你们学习,我专门作了个demo页面:check-foo.html
例如,我点击第一个检查按钮,成功高亮的不合要求的排版内容:
就一个循环外加一大堆if语句,一丁点正则表达式都没实现,就实现了看上去很难的翻译排版校验工具,并且多半比正则实现更稳健。
页面源码能够直接在这个项目的docs目录中找到:github.com/zhangxinxu/…
接下来要引出本次直播答疑最有价值的一个议题,是有关职业发展的,那就是升职加薪与技术强弱没有直接关系。
不少人都有这样一个错误的认识,由于本身的技术越强,薪资就越高,职位就越高,实际上不是这样子的,并无直接的关系。职位的高低是与你对团队,对公司产生的价值相呼应的。做为一个技术人员,就算你的技术能力并非很是的强,也能产生很是高的价值,关键在于认知与意识。
举个例子,某公司某团队打算加入掘金的翻译计划,来提升团队的影响力。
其中有个很重要的环节,那就是校验,而校验这种工做每每都是团队的负责人来作这个事情,负责最后的把关,省得出现一些意外的风险。这就问题来了,一般团队的负责人都是很忙的,要靠肉眼去识别那些翻译中出现的小错误,那是很是费心费力费神费时的事情,长此以往,体验会变得很是糟糕。
这个的团队里面有两个前端,一个技术很是扎实,正则玩得666,但老是沉浸在本身的技术世界里,专一于手头上的事情,以本身代码质量世界第一为自豪。另一个技术通常般,正则玩得233,可是,其敏锐发现翻译排版校验走人工是很是低效的一件事情,因而当机立断决定作了一个工具,能够帮助你们快速的发现一些排版上的问题,解放生产力。虽然技术通常般,但他活用本身已经掌握的一些知识,经过良好的交互设计下降实现成本,用“傻白甜”的方式把这个东西给作出来了,别人一用,嘿,还行。
很显然,这件事情上,那个技术通常般的人创造的价值更大,并且大的很是明显。一我的技术再强,那解放只是你一我的的生产力,团队还有其余好几十号人并无任何提高;可是若是你作出一个可让你们都能提升生产力的工具,就算你技术通常般,可是你对这个团队产生的价值是很是深远的。翻译这种事情,全国有那么多人参加,若是你把这个工具开源出去,对团队带来的影响力要远比翻译一两个文章更高。
对比下:技术强的人本身生产力很高,而后没有而后;技术通常般的人让团队其余人生产力提升,同时经过开源工具给团队带来了影响力。若是你是领导,若是你是boss,你会提拔哪个人?显然,只要领导不是智障,都会升职加薪是后面那个技术通常的人!
不少技术人员一直没有意识到这个问题,常常会抱怨,那我的技术那么烂,为何此次升职晋升的是他?拜托,升职晋升是看贡献,不是看你一我的的技术水平,这个和搞科研是不同的,企业是商业机构。
因此,你们必定要扭转意识,敏锐捕捉能够产生巨大价值的场景,不要只盯着本身的一亩三分地。工做中全部同事遇到的不爽、不悦,全部那些重复人力的场合,都是一次很好的提升你绩效的机会,就算你技术通常般,也能产生很是大的价值;若是你自己技术就很强,那更要抓住这样的机会,不然机会留给了别人,最后怎么被踩下去都不知道,那更惨!
本次直播有录播,由于加班错过的小伙伴能够去围观,地址是:www.bilibili.com/video/av411…
欢迎提出各类意见。
关于群小测
每周三下班后会在微信粉丝群公布一道小测题,每周六上午10:00-11:00会以直播形式对你们的解答进行答疑。
目前一群已满,二群还有坑我,想入的能够加我微信好友 zhangxinxu-job,我拉大家进去,备注“入群”,而后附上大家的姓名,方便我备注。
(完)