知識學到自己手裡的才是自己的,如果複製,貼上別人的對自己幫助並不大,它只能幫自己解決一時的問題(有時還要花費自己大量的時間來查詢),而不能從根本上解決問題。
就好像前段時間我的的大學同學問了我一個正則問題,如何驗證使用者輸入的密碼必須包含字元、數字、特殊符號,他說在百度上找了大量的正則示例都不能解決問題,我就問然後呢,他給我說我問你,我當時就無語了,我當時因為正在做專案,一時沒想出來,我跟他說你沒試著換個思路,暫時沒有找到用一個正則解決這個問題的你就不會試著分別對字元,數字,特殊字元單獨判斷,然後進行與運算不就行了,再者說了從使用者體驗上用一個正則判斷後給出一個結果,使用者體驗也不好,應該針對使用者輸入不同的情況給出不同的提示資訊,如果密碼的組成沒有數字,就提示沒有數字,如果沒有字元就提示沒有字元…… , 如果以此類推覺得判斷過多,你可以再簡化處理,如只有密碼組成包含兩種,就提示缺少的一種,如果密碼組成只包含一種,就提示密碼應該有字元、數字、特殊符號組成。
這無形中給我上了生動的一課,正則不僅其他人忽視了,我也忽視了,有所欠缺。所以儘管最近在努力拿下設計模式這個高地,還是決定抽出一部分時間梳理一下自己的正則知識的掌握。
具有特殊含義的字元
下面只列出常用的字元,以及我個人對它們的分類。
分組和集合
-
()
: 括號內的表示式表示一個分組 -
[]
: 方括號內的表示式表示一個集合
運算子
-
^
: 如果出現在集合([]
)中表示取反,否則是是定位符,從字串的前邊界開始匹配 -
|
:它表示或的意思,就是起到或運算的作用 -
?:
: 它的作用是放在第一個選項前來消除相關匹配會被快取這種副作用
定位符
-
^
: 上面已經說了它定義正則運算的前邊界 -
$
: 它定義了正則運算的後邊界 -
: 匹配一個字元的邊界(也即是字元和空白字元的分界)
字元類(代表一類字元)
-
d
: 代表數字,而D
,非數字 -
w
: 代表單詞,而W
,非單詞 -
s
: 代表空白符,而D
,非空白字元 -
.
: 任意字元
限定符
它是用來指定匹配結果的長度或次數。
匹配該符號前面的表示式
-
+
: 一次或更多次 -
*
:零次或多次 -
?
: 零次或一次 -
{}
: 匹配次數與話括號內的值有關。如果
{n}
,就是匹配n次;
如果{n,}
,就是匹配至少n次;
如果{n,m}
,就是匹配n到m之間的任意次數。
如何玩轉正則
正則用在字串的處理上,可以減少我們的js程式碼的書寫量,優化我們的程式碼,同時對於我們學習別人原始碼中複雜的正則已有幫助。
下面是一張來自知乎關於你是如何學會正規表示式的?問題的一張圖,掌握這張圖的正則,大概你就能解決你所面臨的大部分問題。
/^s*[A-Za-z_$][w$]*(?:.[A-Za-z_$][w$]*|[`*?`]|[".*?"]|[d+]|[[A-Za-z_$][w$]*])*s*$/
下面推薦幾款視覺化的正則編輯器。
regexper (這是我最早接觸到的一款)
Regulex (這一款是我現在經常使用的)
RegExr (這一款功能很強大,對於學習正則很有幫助,如果學習正則的話強烈推薦)
js如何使用
正則是一個很強大的字串查詢和替換的方法。
以前我們有時侯總是在想將字串轉換為數字陣列,利用陣列的方法來處理字元,但是要知道字串就是我們在生活和工作中常見的形式,數字、陣列、Boolean型別的相對較少,尤其是最近在做微信開發時發現正則很重要,我同學的例子,只是給了我一個深入學習和研究的動力,這只是我的初步總結,以後有必要的話還會加強。
在JavaScript中我們使用 RegExp
來建立一個物件來實現正規表示式。
基本定義
一個正則有兩部分組成:正則主體和修飾符。
形式如下:
regExp = new RegExp(`pattern`, `flag`);
// 或者
regExp = /pattern/gmi
正則的修飾符一共有5種,分別為:
-
g
: 所有匹配的情況,如果沒有它,只一種匹配情況 -
i
: 忽略字元的大小寫 -
m
: 支援多行 -
u
: 支援 Unicode -
y
: 嚴格模式(返回指定位置後的匹配結果)
正則物件的一些方法
regexp.test(str)
test
方法返回值為true/false
let str = "Hello world!";
let regexp = /hello/i;
console.log(regexp.test(str));
regexp.exec(str)
由於這個方法不好用,所以很少有人使用。
let str = "Hello world!";
let regexp = /l(o)/ig; // 如果用exec返回所有的的匹配結果需要加上 ‘g’ 修飾符
let matchOne = regexp.exec(str);
console.log(matchOne[0]); // lo
console.log(matchOne[1]); // o
console.log(matchOne.index); // 3
console.log(matchOne.input); // Hello world!
console.log(matchOne.lastIndex); // 5
如果沒有匹配返回null
js中String可以使用正則的方法
在String的方法中使用正則,可以輕鬆的解決我們日常開發中的問題。
str.search()
如果有匹配結果,返回第一個匹配結果的首字元位置;否則,返回 `-1`。
let str = "Hello world!";
regexp = /o/i;
str.search(regexp); // 4
注;search
只能返回第一次匹配的結果,而不能返回其他匹配結果
str.match(str|reg)
let str = "Hello world!";
regexp = /o/i;
let result = str.match(regexp);
console.log(result[0]); // o
console.log(result.index); // 4
console.log(result.input); // Hello world!
我們發現 str.match()
的用法和 regexp.exec()
返回的結果很一樣,其實match的底層實現就是 regexp.exec()
,使用也一樣,注意修飾符 g
。
str.split(reg|substr, limit)
將給定的字串按單詞為單位進行分割,返回一個由單片語成的陣列。
let str = `Hello world, my name is lzb.`
let regexp = /s+/i;
str.split(regexp); // ["Hello", "world,", "my", "name", "is", "lzb."]
str.split(regexp, 3) // ["Hello", "world,", "my"]
在這個字串的方法中第二引數限制返回結果陣列的長度。
在返回的結果中,我們發現有的單詞帶有特殊符號,下面一個字串方法將實現清除特殊符號。
str.replace(str|reg, str|func)
如果要實現上面示例的清除字元中特殊符號的目標,我們可以使用 str.replace()
,效果如下:
let str = `Hello world, my name is lzb.`
let regexp = /[.,/#!$%^&*;:{}=-_`~()]/g;
str.replace(regexp, ``); // "Hello world my name is lzb"
或者
let str = `Hello world, my name is lzb.`
let regexp = /[^ws|-]/g;
str.replace(regexp, ``); // "Hello world my name is lzb"
然後,接著使用上面的 str.split()
方法即可,或者有同學可能想到如下方法:
let str = `Hello world, my name is u-lzb.`
let regexp = /[^w]+/g;
str.split(regexp); // ["Hello", "world", "my", "name", "is", "u", "lzb", ""]
這種方法不建議使用,問題很明顯,這裡就不多說了。
我們發現上面實現清除字串中特殊符號的方法有兩種,這兩種方法談不上孰優孰劣,它們各有優勢。如果在我們把字串中 work_up
, call&apply
,::arg
,a=b
… 都當作特殊的單詞,我們就需要第一種方法;如果我們就是要中規中矩的單詞我們可以使用第二種方法。
如果第二個引數是func,介紹一個例子,字串中單詞的首字母大寫:
let str = `hello world`;
str.replace(/w+/g, (word) => word.substring(0,1).toUpperCase() + word.substring(1) );
字串還有 length
,indexOf
,concat
,toLowerCase
,toUpperCase
等方法,這裡就不一一介紹了。
推薦
如果喜歡碼題的同學可到https://www.hackerrank.com/domains/regex/re-introduction這個網站去。