原文地址: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,我拉大家進去,備註「入羣」,而後附上大家的姓名,方便我備註。
(完)