玩轉正則表達式,就是這麼簡單

在平時開發中,正則表達式用的好能節省很大的工作量,舉個例子
將字符串格式化成數組(數字不格式化), 例如: 張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 
.:任意字符 
[0­9a­zA­z\_]: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的範圍的字符

例如匹配010­123456的正則爲:\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表示重複正則第二個圓括號內匹配到的內容
*/

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章