在平時開發中,正則表達式用的好能節省很大的工作量,舉個例子
將字符串格式化成數組(數字不格式化), 例如: 張123四 => ["張", "123", "四"];
如果使用原生js的話,需要這麼寫:
function transArrExcluNnm(str){
var arr = str.split('');
var arrnew = [],numstr = '',isNum=false;;
for(var i=0;i<arr.length;i++){
var item = arr[i];
if(/\d/.test(item)){
isNum = true;
numstr = numstr + String(item);
continue
}else{
if(isNum){arrnew.push(numstr);numstr='';isNum=false;}
arrnew.push(item)
}
}
return arrnew;
}
transArrExcluNnm('我1說123木頭09人');
// ["我", "1", "說", "123", "木", "頭", "09", "人"]
隨隨便便都要是多行代碼,如果使用正則,只需要一行就搞定了str.match(/\d+|[^0-9]/gi);
'我1說123木頭09人'.match(/\d+|[^0-9]/gi); // ["我", "1", "說", "123", "木", "頭", "09", "人"]
所以作爲一個開發人員,掌握正則的基本用法,可以提高代碼質量.
那麼什麼是正則呢?
正則表達式(regular expression)描述了一種字符串匹配的模式(pattern),可以用來檢查一個串是否含有某種子串、將匹配的子串替換或者從某個串中取出符合某個條件的子串等
作爲一個開發人員,怎麼調試正則呢?(博主是直接打開瀏覽器,在console裏面調試)
當然喜歡用調試工具的也可以訪問這:http://rubular.com/
好了言歸正傳,我們來說說正則中的常用的正則表達式以及語法
使用一個正則表達式字面量,其由包含在斜槓之間的模式組成,如下所示:
var re = /ab+c/;
腳本加載後,正則表達式字面量就會被編譯。當正則表達式保持不變時,使用此方法可獲得更好的性能。
或者調用RegExp
對象的構造函數,如下所示:
var re = new RegExp("ab+c");
在腳本運行過程中,用構造函數創建的正則表達式會被編譯。如果正則表達式將會改變,或者它將會從用戶輸入等來源中動態地產生,就需要使用構造函數來創建正則表達式。
正則表達式中的特殊字符
\d:數字
\w:字母或數字
\s:空格或tab
.:任意字符
[09azAz\_]:0到9或小寫字母或大寫字母或下劃線
A|B:A或B(例如(P|p)ython匹配'Python'或'python')
\:轉譯字符
*:0個或多個
+:1個或多個
?:0個或1個
{n}:正好N個
{n,m}:n至m個
|:匹配左右任意一個表達式
(ab):將括號中字符作爲一個分組
\num:引用分組num匹配到的字符串
\n:表示第n個被捕獲括號匹配的子字符串,而replace則使用$n來匹配括號裏的子串
例:/(a)(b)\d*\1\2/ : \1和\2分別表示第一個括號和第二個括號中的規則 即: /(a)(b)\d*(a)(b)/
/(a)(b)\d*\1\2/.test('ab0ab') // true;
/(a)(b)\d*\1\2/.test('ab0ee') // false
例:'123-李四'.replace(/(\d+)\-(\D+)/,'$2,$1'); // "李四,123"
其中$1匹配的是(\d+)的結果,$2匹配的是(\D+)的結果
(?P<name>):分組起別名
(?P=name):引用別名爲name分組匹配到的字符串
^:行的開頭,
^\d表示必須以數字開頭
$:行的結尾,例如,/t$/ 並不會匹配 "eater" 中的 't',但是會匹配 "eat" 中的 't'。
\d$表示必須以數字結尾
^在[]裏還可表示反向字符範圍:[^a‐z] #匹配不在a‐z的範圍的字符
例如匹配010123456的正則爲:\d{3}\\d{3,8}
匹配手機號:1[358]\d{9}
匹配圖片:r"https://.*?\.[jpng]{3}"
使用正則表達式的方法
方法 | 描述 |
---|---|
exec |
一個在字符串中執行查找匹配的RegExp方法,它返回一個數組(未匹配到則返回 null)。 |
test |
一個在字符串中測試是否匹配的RegExp方法,它返回 true 或 false。 |
match |
一個在字符串中執行查找匹配的String方法,它返回一個數組,在未匹配到時會返回 null。 |
matchAll |
一個在字符串中執行查找所有匹配的String方法,它返回一個迭代器(iterator)。 |
search |
一個在字符串中測試匹配的String方法,它返回匹配到的位置索引,或者在失敗時返回-1。 |
replace |
一個在字符串中執行查找匹配的String方法,並且使用替換字符串替換掉匹配到的子字符串。 |
split |
一個使用正則表達式或者一個固定字符串分隔一個字符串,並將分隔後的子字符串存儲到數組中的 String 方法。 |
search/split/test/replace
// search: str.search(reg)
var str="Visit W3School!"
str.search(/W3School/) // 6
str.search(/sdf/) // -1
// split: str.split(reg)
var str="貂蟬love呂布"
var result = str.split(/[a-z]+/g) // 以規則/[a-z]+/g來分割str
// 等價於var result = str.split(new RegExp("[a-z]+", "g"))
console.log(result) // ["貂蟬", "呂布"]
// test: reg.test(str)
/\d/.test('Visit W3School!'); // true
// replace: str1.replace(reg, str2)
'Visit W3School!'.replace(/\d/, '替換數字'); // "Visit W替換數字School!"
match/exec
由下面的運行結果可以看出,
exec:不管正則是否加全局,返回的內容是一樣的
match:
非全局正則,可以返回捕獲組,也就是正則裏面()裏面的內容,但不能多次匹配;
全局正則,可以多次匹配,但不返回捕獲組;
matchAll :返回一個數組集合,使用...展開的話會發現,裏面是匹配到的子穿
正則表達式執行後的返回信息
var myRe = /d(b+)d/g; // var myRe = new RegExp("d(b+)d", "g")
var myArray = myRe.exec("cdbbdbsbz");
console.log(myArray) // ["dbbd", "bb", index: 1, input: "cdbbdbsbz", groups: undefined]
console.log(myRe.lastIndex) // 5
console.log(myRe.source) // "d(b+)d"
對象 | 屬性或索引 | 描述 | 在例子中對應的值 |
---|---|---|---|
myArray |
匹配到的字符串和所有被記住的子字符串(即每一個括號中的匹配到的)。 | ["dbbd", "bb"] |
|
index |
在輸入的字符串中匹配到的以0開始的索引值。 | 1 |
|
input |
初始字符串。 | "cdbbdbsbz" |
|
[0] |
匹配到的所有字符串(並不是匹配後記住的字符串)。注:原文"The last matched characters.",應該是原版錯誤。匹配到的最終字符。 | "dbbd" |
|
myRe |
lastIndex |
下一個匹配的索引值(必須以變量保存的形式纔有值,像/d(b+)d/g.lastIndex的話結果就是0)。注意:這個屬性只有在使用g參數時可用 | 5 |
source |
模式文本。在正則表達式創建時更新,不執行。 | "d(b+)d" |
使用括號的子字符串匹配
一個正則表達式模式使用括號,將導致相應的子匹配被記住。例如,/a(b)c /可以匹配字符串“abc”,並且記得“b”。回調這些括號中匹配的子串,使用數組元素[1],……[n]。
使用括號匹配的子字符串的數量是無限的。返回的數組中保存所有被發現的子匹配。下面的例子說明了如何使用括號的子字符串匹配。
下面的腳本使用replace()方法來轉換字符串中的單詞。在匹配到的替換文本中,腳本使用替代的$ 1,$ 2表示第一個和第二個括號的子字符串匹配。
var re = /(\w+)\s(\w+)/;
var str = "John Smith";
var newstr = str.replace(re, "$2, $1");
console.log(newstr); // Smith, John
通過標誌進行高級搜索,下面是正則表達式標誌
g |
全局搜索。 |
i |
不區分大小寫搜索。 |
m |
多行搜索。 |
s |
允許 . 匹配換行符。 |
u |
使用unicode碼的模式進行匹配。 |
y |
執行“粘性”搜索,匹配從目標字符串的當前位置開始,可以使用y標誌。 |
爲了在正則表達式中包含標誌,請使用以下語法:
var re = /pattern/flags;
// 或者
var re = new RegExp("pattern", "flags");
值得注意的是,標誌是一個正則表達式的一部分,它們在接下來的時間將不能添加或刪除。
var re = /\d+|[^0-9]/g; // 等價於 var re = new RegExp("\d+|[^0-9]", "g");
var str = '我1說123木頭09人';
var myArray = str.match(re);
console.log(myArray);
// ["我", "1", "說", "123", "木", "頭", "09", "人"]
一些簡單匹配
// 簡單的匹配
var s1 = 'abc‐123456'
var m1 = /^[a-z]{3}‐\d{3,6}$/
s1.match(m1)
// 結果: ["abc‐123456", index: 0, input: "abc‐123456", groups: undefined]
// | 的用法
"08".match(/[1‐9]?\d$|100/)
// 結果: ["8", index: 1, input: "08", groups: undefined]
// 匹配開頭結尾:
"<html>hh</html>".match(/<[a-zA-Z]*>\w*<\/[a-zA-Z]*>/)
// 結果: ["<html>hh</html>", index: 0, input: "<html>hh</html>", groups: undefined]
// 組的匹配:
'abc‐123456'.match(/^([a-z]{3})‐(\d{3,6})$/)
// 結果: ["abc‐123456", "abc", "123456", index: 0, input: "abc‐123456", groups: undefined]
// 貪婪匹配: 正則默認使用貪婪匹配,也就是匹配儘可能多的字符:
'12300'.match(/^(\d+)(0*)$/)
// 結果: ["12300", "12300", "", index: 0, input: "12300", groups: undefined]
//前面的\d+採用貪婪匹配把所有的數字全給匹配了,導致第二組的0*匹配了個空字符串,如果想讓後面的0* 也匹配到,可用?使前面的\d+不使用貪婪匹配:
'12300'.match(/^(\d+?)(0*)$/)
// 結果: ["12300", "123", "00", index: 0, input: "12300", groups: undefined]
// 匹配一個變量
const sendPostKey = '西湖';
const PosKey = '杭州西湖商圈';
const re = new RegExp(sendPostKey, 'gi');
const buleStrHtml = PosKey.replace(re, '<span class="col2a86e8">' + sendPostKey + '</span>');
console.log(buleStrHtml); //杭州<span class="col2a86e8">西湖</span>商圈"
如果遇到非正常的html格式字符串,匹配出錯
// 如果遇到非正常的html格式字符串,匹配出錯
"<html>hh</htmlbalabala>".match(/<([a-zA-Z]*)>\w*<\/\1>/)
// 結果: null
"<html>hh</html>".match(/<([a-zA-Z]*)>\w*<\/\1>/)
// 結果: ["<html>hh</html>", "html", index: 0, input: "<html>hh</html>", groups: undefined]
/*
注意:這個\1 \2...... 都要和正則表達式集合()一起使用
簡單的說就是
\1表示重複正則第一個圓括號內匹配到的內容
\2表示重複正則第二個圓括號內匹配到的內容
*/