粉絲羣第27期JS小測直播答疑文字版

原文地址:www.zhangxinxu.com/wordpress/2…css

1、題目

小測題目

就是寫一個檢驗方法,輸出不符合排版規則的內容。html

翻譯規則地址:譯文排版規則指南前端

補充細節:git

  1. 數字與單位之間須要增長空格只須要考慮後面是大寫字母的場景,由於代碼中常常會有相似20px這樣的處理,中間不能有空格。
  2. 標點不能重複專指中文標點,英文標點不考慮,在程序代碼中標點重複很常見。

對於字符內容的格式驗證,天然就是正則表達式了,所以,本期的題目主要目的之一是學習正則表達式。程序員

正則表達式規則在全部的語言中都是通用的,除了細節上上有些差別,須要的是如出一轍的,因此學會了JS中的正則表達式,其餘開發語言也能夠受用,包括CSS這麼語言(CSS中也有正則表達式)。github

JS這麼語言要想基礎紮實,正則表達式必定要好好學習,學到滴水不漏,能夠極大提高處理本身的開發效率。包括在其餘一些場合解放生產力,比方說Sublime Text這種編輯器在替換的時候是支持正則表達式的,若是你會正則表達式,則簡單幾個字符就能完成複雜替換,並且毫不會遺漏。那種解放生產力的感受,會讓你以爲,會代碼真的好棒,好high!感受人生已經達到了高潮。正則表達式

2、幾個驗證的實現

CSS題目收到近50份回答,此次的正則小測,只有4個實現,人雖少,但都是精英。express

其中第一位@XboxYan的回答幾乎直接大結局,我就以這我的回答做爲案例講講正則表達式相關的一些東西。bash

測試結果示意

1. 中英文之間須要增長空格

/([\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,還有im。其中i表示不區分大小寫,m表示支持多行匹配。

所以,這裏的正則能夠進一步簡化:

/[\u4e00-\u9fa5][a-z]|[a-z][\u4e00-\u9fa5]/gi複製代碼

2. 中文與數字之間須要增長空格

/([\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表示換行。

3. 數字與單位之間須要增長空格

/\d[A-Za-z]+/g複製代碼

題目這個需求是不合理的,有些數字和單位之間是不能加空格的,有趣技術文章翻譯,一定包含大量的代碼,例如10px等,顯然不能加空格。所以,能夠認爲數字和大寫字母之間須要空格。

所以,正則能夠調整爲:

/\d[A-Z]+/g複製代碼

4. 全角標點與其餘字符之間不加空格

/([\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()來實現。

5. 不重複使用標點符號

這裏的標點指中文標點,由於英文標點不重複,有些不切實際,例如空字符串'',就是合法的重複標點。

本來的實現:

/(\~|\`|\!|\[|\]|\{|\}|\;|\:|\"|\'|\,|\<|\.|\>|\/|\?|\!|\·|\【|\】\「\」|\;|\:|\「|\」|\,|\《|\。|\》|\、|\?)\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進行處理,返回咱們須要的值
})複製代碼

6. 破折號先後須要增長一個空格

這個超easy:

/(\S(——)|(——)\S)/g複製代碼

這裏幾個括號都是多餘的,直接下面這樣既可:

/\S——|——\S/g複製代碼

7. 使用全角中文標點

/([^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');複製代碼

8. 數字使用半角

也就是須要匹配10個全角數字,鬆鬆的,沒什麼好說。

/[\uFF10-\uFF19]+/g複製代碼

9. 遇到完整的英文整句,其內容使用半角標點

/(\「[A-Za-z\s\~|\`|\!|\;|\:|\"|\'|\,|\<|\.|\>|\/|\?]*[\!|\·|\;|\:|\「|\」|\,\。|\、|\?][^\」]*\」)|(\《[A-Za-z\s\~|\`|\!|\;|\:|\"|\'|\,|\<|\.|\>|\/|\?]*[\!|\·|\;|\:|\「|\」|\,\。|\、|\?][^\》]*\》)/g複製代碼

完整的英文整句的重要特徵是單詞與空格,考慮到標點以後可能會有空格,因而,優化了下:

new RegExp(`([a-z]+[${regPunct}|\\s])+[a-z]*([${regPunct}|\\s][a-z]+)+`, 'gi')複製代碼

足以如今知足大多數的場景。

3、在線驗證工具出爐

如今咱們有了基礎技術,但還不足以做爲工具,做爲產品讓更多人使用,由於在控制檯輸出這種事情非程序員之外的人是作不來的。

因此,能夠將其變成可視化工具。

最後一個回答者@wingmeng參照了 @XboxYan 的一些思路除了輸出驗證結果,還輸出了處理後的正確排版。

輸出正確結果

因而,站在這兩位的肩膀上,我熬夜搞出了一個「翻譯內容格式檢驗工具」 —— check.html

直接輸入內容,就能夠高亮標記錯誤的翻譯排版,同時顯示正確的結果。

可視化翻譯內容校驗工具

能夠大大減輕校對時候的工做量,若是你也有參加掘金的翻譯計劃,或者本身平時翻譯文章什麼的,這個小工具能夠試一試,雖不能100%完美解決各類排版問題,但至少能夠解決大部分的問題,很是划算。

4、正則很爛也能實現的傻白甜方法

回到題目以外,在實際項目中遇到這樣的排版驗證需求,本質上就是用工程化的手段讓普通人也能發現一些翻譯排版的問題,所以,實際上,就算你正則表達式很是的爛,甚至一點也不會,你也能弄出一個可使用的工具來解放生產力。

首先經過交互設計手段來下降咱們實現的成本:

  1. 咱們沒有必要一次性全部的規則一次性匹配,我可讓用戶選擇具體哪條規則,到時候一個一個規則匹配就行了,用戶徹底不care的;
  2. 沒有必要匹配全部的排版規則,比方說最後單詞英文後面是全角標點,整句英文還使用半角標點,有些難度,也有些蛋疼,咱們大不了忽略。由於原本就是輔助工具,不必面面俱到。

而後,判斷什麼類型的字符,能夠不用走高大上、學習成本較高的正則表達式,能夠試試基於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/…

5、升職加薪與技術強弱沒有直接關係

接下來要引出本次直播答疑最有價值的一個議題,是有關職業發展的,那就是升職加薪與技術強弱沒有直接關係。

不少人都有這樣一個錯誤的認識,由於本身的技術越強,薪資就越高,職位就越高,實際上不是這樣子的,並無直接的關係。職位的高低是與你對團隊,對公司產生的價值相呼應的。做爲一個技術人員,就算你的技術能力並非很是的強,也能產生很是高的價值,關鍵在於認知與意識。

舉個例子,某公司某團隊打算加入掘金的翻譯計劃,來提升團隊的影響力。

其中有個很重要的環節,那就是校驗,而校驗這種工做每每都是團隊的負責人來作這個事情,負責最後的把關,省得出現一些意外的風險。這就問題來了,一般團隊的負責人都是很忙的,要靠肉眼去識別那些翻譯中出現的小錯誤,那是很是費心費力費神費時的事情,長此以往,體驗會變得很是糟糕。

這個的團隊裏面有兩個前端,一個技術很是紮實,正則玩得666,但老是沉浸在本身的技術世界裏,專一於手頭上的事情,以本身代碼質量世界第一爲自豪。另一個技術通常般,正則玩得233,可是,其敏銳發現翻譯排版校驗走人工是很是低效的一件事情,因而當機立斷決定作了一個工具,能夠幫助你們快速的發現一些排版上的問題,解放生產力。雖然技術通常般,但他活用本身已經掌握的一些知識,經過良好的交互設計下降實現成本,用「傻白甜」的方式把這個東西給作出來了,別人一用,嘿,還行。

很顯然,這件事情上,那個技術通常般的人創造的價值更大,並且大的很是明顯。一我的技術再強,那解放只是你一我的的生產力,團隊還有其餘好幾十號人並無任何提高;可是若是你作出一個可讓你們都能提升生產力的工具,就算你技術通常般,可是你對這個團隊產生的價值是很是深遠的。翻譯這種事情,全國有那麼多人蔘加,若是你把這個工具開源出去,對團隊帶來的影響力要遠比翻譯一兩個文章更高。

對比下:技術強的人本身生產力很高,而後沒有而後;技術通常般的人讓團隊其餘人生產力提升,同時經過開源工具給團隊帶來了影響力。若是你是領導,若是你是boss,你會提拔哪個人?顯然,只要領導不是智障,都會升職加薪是後面那個技術通常的人!

不少技術人員一直沒有意識到這個問題,常常會抱怨,那我的技術那麼爛,爲何此次升職晉升的是他?拜託,升職晉升是看貢獻,不是看你一我的的技術水平,這個和搞科研是不同的,企業是商業機構。

因此,你們必定要扭轉意識,敏銳捕捉能夠產生巨大價值的場景,不要只盯着本身的一畝三分地。工做中全部同事遇到的不爽、不悅,全部那些重複人力的場合,都是一次很好的提升你績效的機會,就算你技術通常般,也能產生很是大的價值;若是你自己技術就很強,那更要抓住這樣的機會,不然機會留給了別人,最後怎麼被踩下去都不知道,那更慘!

6、關於本次直播

本次直播有錄播,由於加班錯過的小夥伴能夠去圍觀,地址是:www.bilibili.com/video/av411…

錄播視頻截圖

歡迎提出各類意見。

關於羣小測

每週三下班後會在微信粉絲羣公佈一道小測題,每週六上午10:00-11:00會以直播形式對你們的解答進行答疑。

目前一羣已滿,二羣還有坑我,想入的能夠加我微信好友 zhangxinxu-job,我拉大家進去,備註「入羣」,而後附上大家的姓名,方便我備註。

(完)

相關文章
相關標籤/搜索