數據/字符串處理是工做中常常能用到的,之前的作法大都是經過百度而後修改別人的代碼完成字符串處理,一直想系統的跟正則認識一番,因而有了這篇。java
點擊《正則表達式》可查看原文哦!
同時很是感謝雪峯大大和鑫大大的文章支持,點擊如下連接可查看參考原文。
雪峯大大的 標準對象/RegExp.
鑫大大的 粉絲羣第27期JS基礎小測答疑文字版python
好的,接下來進入正題啦。正則表達式
正則表達式是對字符串操做的一種邏輯公式,用事先定義好的一些特定字符、及這些特定字符的組合,組成一個「規則字符串」,這個「規則字符串」用來表達對字符串的一種過濾邏輯。
舉個例子:
'00\d'能夠匹配'007',‘008’,其中‘\d’即匹配數字。數組
字 符 | 描 述 | 反義字符 | 描 述 |
---|---|---|---|
$ | 匹配輸入字符串的結尾位置 | ||
^ | 匹配輸入字符串的開始位置 | ||
. | 匹配除換行符 \n 以外的任何單字符 | ||
\b | 匹配單詞邊界 | \B | 匹配不是單詞開頭或結束的位置 |
\d | 匹配數字 | \D | 匹配任意非數字的字符 |
\w | 匹配字母,數字,下劃線 | \W | 匹配任意不是字母,數字,下劃線 的字符 |
\s | 匹配空格 | \S | 匹配任意不是空白符的字符 |
[abc] | 匹配包含括號內元素的字符 | [^abc] | 匹配除了abc之外的任意字符 |
字 符 | 描 述 | 帶?字符 | 描 述 |
---|---|---|---|
* | 重複至少0次 | *? | 重複任意次,但儘量少重複 |
+ | 重複至少1次 | +? | 重複至少1次,但儘量少重複 |
? | 重複0次或1次 | ?? | 重複0次或1次,但儘量少重複 |
{n} | 重複n次 | ||
{n,} | 重複至少n次 | {n,}? | 重複至少n次,但儘量少重複 |
{n,m} | 重複n-m次 | {n,m}? | 重複n-m次,但儘量少重複 |
字 符 | 描 述 | 字 符 | 描 述 |
---|---|---|---|
\cx | 匹配由x指明的控制字符。 | ||
\f | 匹配一個換頁符。等價於 \x0c 和 \cL。 | ( ) | 標記一個子表達式的開始和結束位置。 |
\n | 匹配一個換行符。等價於 \x0a 和 \cJ。 | | | 指明兩項之間的一個選擇,或 |
\r | 匹配一個回車符。等價於 \x0d 和 \cM。 | [ | 標記一箇中括號表達式的開始 |
\s | 匹配任何空白字符,包括空格、製表符、換頁符等等。 | \ | 將下一個字符標記爲或特殊字符、或原義字符、或向後引用、或八進制轉義符 |
\S | 匹配任何非空白字符。等價於 [^ \f\n\r\t\v]。 | { | 標記限定符表達式的開始。 |
\t | 匹配一個製表符。等價於 \x09 和 \cI。 | \v | 匹配一個垂直製表符。等價於 \x0b 和 \cK。 |
數字、字母匹配(\d
匹配數字,\w
匹配任意字母,數字,下劃線)
可用00\d
能夠匹配007
\d\d\d
能夠匹配任意三位數字,如:123
\w\d\w
能夠匹配l0l
wordpress
.
匹配任意字符,則
any.
可匹配anya
、anyb
、anyc
、anyd
......ui
配合上量詞再看看
\d{3}
表示匹配3個數字,例如010
\d{3,8}
表示3-8個數字,例如1234567
this
再加上咱們的範圍
[0-9a-zA-Z\_]
能夠匹配一個數字、字母或者下劃線
[0-9a-zA-Z\_]+
能夠匹配至少由一個數字、字母或者下劃線組成的字符串,好比a100
,0_Z
,Py3000
等等
[a-zA-Z\_][0-9a-zA-Z\_]*
能夠匹配由字母或下劃線開頭,後接任意個由一個數字、字母或者下劃線組成的字符串,也就是Python合法的變量
[a-zA-Z\_][0-9a-zA-Z\_]{0, 19}
更精確地限制了變量的長度是1-20個字符(前面1個字符+後面最多19個字符)spa
啊,還有咱們的選擇字符和定位
A|B
能夠匹配A或B,因此(P|p)ython
能夠匹配Python
或者python
^
表示行的開頭,^\d
表示必須以數字開頭 $
表示行的結束,\d$
表示必須以數字結束
你可能注意到了,py
也能夠匹配python
,可是加上^py$
就變成了整行匹配,就只能匹配py
了prototype
字符串的切割
最經常使用的應該就是split切割了,可是當字符串之間不只僅是單一字符鏈接,切割就會出現問題,好比下面的例子code
//出現多餘空格狀況:
'a b c'.split(' '); // ['a', 'b', '', '', 'c']
//嗯,沒法識別連續的空格,用正則表達式試試:
'a b c'.split(/\s+/); // ['a', 'b', 'c']
//不管多少個空格均可以正常分割。加入,試試:
'a,b, c d'.split(/[\s\,]+/); // ['a', 'b', 'c', 'd']
//再加入;試試:
'a,b;; c d'.split(/[\s\,\;]+/); // ['a', 'b', 'c', 'd']
//若是用戶輸入了一組標籤,下次記得用正則表達式來把不規範的輸入轉化成正確的數組。
複製代碼
字符串的分組應用
除了簡單地判斷是否匹配以外,正則表達式還有提取子串的強大功能。用()表示的就是要提取的分組(Group)。好比:^(\d{3})-(\d{3,8})$
分別定義了兩個組,能夠直接從匹配的字符串中提取出區號和本地號碼:
var re = /^(\d{3})-(\d{3,8})$/;
re.exec('010-12345'); // ['010-12345', '010', '12345']
re.exec('010 12345'); // null
複製代碼
若是正則表達式中定義了組,就能夠在RegExp對象上用exec()方法提取出子串來。
exec()方法在匹配成功後,會返回一個Array,第一個元素是正則表達式匹配到的整個字符串,後面的字符串表示匹配成功的子串。
exec()方法在匹配失敗時返回null。
提取子串很是有用。來看一個更兇殘的例子:
var re = /^(0[0-9]|1[0-9]|2[0-3]|[0-9])\:(0[0-9]|1[0-9]|2[0-9]|3[0-9]|4[0-9]|5[0-9]|[0-9])\:(0[0-9]|1[0-9]|2[0-9]|3[0-9]|4[0-9]|5[0-9]|[0-9])$/;
re.exec('19:05:30'); // ['19:05:30', '19', '05', '30']
複製代碼
這個正則表達式能夠直接識別合法的時間。可是有些時候,用正則表達式也沒法作到徹底驗證,好比識別日期:
var re = /^(0[1-9]|1[0-2]|[0-9])-(0[1-9]|1[0-9]|2[0-9]|3[0-1]|[0-9])$/;
複製代碼
對於'2-30','4-31'這樣的非法日期,用正則仍是識別不了,或者說寫出來很是困難,這時就須要程序配合識別了。
如下內容參見鑫大大博客內容:
中英文之間須要增長空格
首先,咱們的思路應該是「中文」、「英文」、「空格」,因而咱們可獲得 /(中文+英文+|英文+中文+)/g
這樣的符號表達
轉換成正則符號即: /([\u4e00-\u9fa5]+[A-Za-z]+|[A-Za-z]+[\u4e00-\u9fa5]+)/g
其中[\u4e00-\u9fa5]
表示中文字符匹配;[A-Za-z]
表示所有的英文字母。斜槓後面的g
表示全局匹配,除了g,還有i和m。其中i表示不區分大小寫,m表示支持多行匹配。 這裏的括號和加號可化簡,則最終可表達爲:
/[\u4e00-\u9fa5][a-z]|[a-z][\u4e00-\u9fa5]/gi
全角標點與其餘字符之間不加空格
這裏若是直接用正則表達式,會顯得冗餘且不易懂,故使用RegExp對象簡化
// 全角標點字符們
var strPunct = '!()【】『』「」《》「」‘’;:,。?、';
// 使用管道符鏈接
var regPunct = strPunct.split('').join('|');
// 此時的正則表達式
new RegExp('['+ regPunct +'] +| +['+ regPunct +']', 'g');
複製代碼
這樣就顯得簡潔多了
其中,空格使用普通空格字符進行匹配的,而不是\s,這樣能夠避免把換行符也過濾掉了
不重複使用標點符號
這裏的標點指中文標點,由於英文標點不重複,有些不切實際,例如空字符串'',就是合法的重複標點。
使用正則表達式:
/(\~|\`|\!|\[|\]|\{|\}|\;|\:|\"|\'|\,|\<|\.|\>|\/|\?|\!|\·|\【|\】\「\」|\;|\:|\「|\」|\,|\《|\。|\》|\、|\?)\1+/g 複製代碼
使用RegExp對象簡化:
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進行處理,返回咱們須要的值
})
複製代碼
破折號先後須要增長一個空格
這個比較簡單,可直接得到:
/\S——|——\S/g
複製代碼
使用全角中文標點
正則表達式
/([^A-Za-z][\~|\`|\!|\[|\]|\{|\}|\;|\:|\"|\'|\,|\<|\.|\>|\/|\?][^A-Za-z])/g 複製代碼
使用RegExp對象處理:
var strPunctHalf = '!()[]"\';:,.?';
// 不一樣於全角字符,半角字符須要加轉義
var regPunctHalf = strPunctHalf.split('').join('|\\');
// 此時的正則表達式
new RegExp(`[\u4e00-\u9fa5][a-z]*( *[${regPunctHalf}] *)|( *[${regPunctHalf}] *)[a-z]*[\u4e00-\u9fa5]`, 'gi');
複製代碼
數字使用半角
/[\uFF10-\uFF19]+/g
遇到完整的英文整句,其內容使用半角標點
正則表達式
/(\「[A-Za-z\s\~|\`|\!|\;|\:|\"|\'|\,|\<|\.|\>|\/|\?]*[\!|\·|\;|\:|\「|\」|\,\。|\、|\?][^\」]*\」)|(\《[A-Za-z\s\~|\`|\!|\;|\:|\"|\'|\,|\<|\.|\>|\/|\?]*[\!|\·|\;|\:|\「|\」|\,\。|\、|\?][^\》]*\》)/g 複製代碼
RegExp對象處理:
new RegExp(`([a-z]+[${regPunct}|\\s])+[a-z]*([${regPunct}|\\s][a-z]+)+`, 'gi')
複製代碼
正則表達式的介紹就先到這裏啦,怎麼樣,動手使用吧~~~