摘要:前言寫這篇文章不是空穴來風,最近一個禮拜寫了一個簡單的腳本,用來處理上千個文件,以便于在某些特定字符的周圍添加標記,先說一下我這個腳本使用場景主要是來識別中文具體做什么,之后會多帶帶寫一篇文章,此處只提該腳本作用,同時為不同的文件類型,包括,
前言
寫這篇文章不是空穴來風,最近一個禮拜寫了一個簡單的nodejs腳本,用來處理上千個文件,以便于在某些特定字符的周圍添加標記,先說一下我這個腳本使用場景主要是來識別中文(具體做什么,之后會多帶帶寫一篇文章,此處只提該腳本作用),同時為不同的文件類型,包括js,vm,jsp等等文件的中文周圍添加標記,以便于減少人工添加標記的事件。
注:本文著重用示例講解,理論知識推薦此篇文章 http://www.jb51.net/tools/zhe... 最早我就是看的這篇文章初步接觸正則,正則剛開始很枯燥,慢慢學就好了,加油!!!
1. 正則理論部分簡介只是看下面的這些還是處于懵逼狀態,其實直接看第二節例子即可,為了完整性此處便于大家查閱!
[] 集合
{} 范圍
() 分組
| 并列關系
+ 一次或者多次(范圍簡寫方式1)
* 零次或多次(范圍簡寫方式2)
? 零次或一次(范圍簡寫方式3) 另外和貪婪模式有關,后面會講
^ 兩個功能,放在開始作為開始符,放在[]的開頭作為“非”
$ 結束符
轉義
(?=pattern) 正向肯定環視(這個名字好多地方都不一樣,斷言,預查,我最喜歡環視,同下)
(?!pattern) 正向否定環視
(?<=pattern) 逆向肯定環視
(? 逆向否定環視
. 匹配除換行符之外的所有字符(此項以下為范圍集)
s 匹配任何空白字符,包括空格、制表符、換頁符等等。
S 匹配任何非空白字符(s的反面)
d 匹配數字字符
D 匹配非數字字符(d的反面)
w 匹配字母、數字、下劃線
W 匹配非字母、數字、下劃線
以上這些我覺得就是比較常用的基本能夠夠大家使用的了,對于中文站一般還會用到中文的相關匹配,那么中文的匹配為[u4e00-u9fa5],其中u是四個十六進制數字表示的Unicode字符,不知道匹配的中文是否全,但是大部分還都是可以的
2. 正則簡單調試實際上調試正則可以不需要什么工具,你要非得要的話,可以用Note Pad++,這個簡單的編輯器內置有正則的匹配,Ctrl+F彈出對話框里邊是含有正則選擇項,打上對勾即可以在編輯其中寫內容,看看能否搜索到了。
我建議看此篇文章或者練習的時候,在chrome瀏覽器直接Windows系統按F12, Mac上按command+option+J,點擊console或者控制臺,用什么瀏覽器自行研究如何打開控制臺,如圖
光標位置即可操作js,然后利用js的就可以展示你寫的正則是否正確,很速度的方式,可以用上下鍵來切換,迅速修改你的表達式
3. JS相關處理函數下文的Reg代表正則表達式,str代表要匹配的字符串,由于還未開始正則表達式講解,如果有無法理解請略讀,了解如何利用這幾個函數,然后開始進行第四節正則學習,然后回頭看就OK了。
RegExp方法test
用法:Reg.test(str)
返回值:Boolean
實例:/a/.test("a") // true
exec
用法:Reg.exec(str)
返回值:Array或null
實例1:/b(a)/.exec("ba") // ["ba", "a", index: 0, input: "ba"]
實例2:/a(c)/.exec("ba") // null
解釋:匹配的值會按照順序-->全匹配,第一分組,第二分組...等等,匹配到的字符串位置(index),輸入的字符串(input)
match
用法:str.match(Reg)
返回值:Array或null
其實和RegExp的test方法是一致的,只不過這個字符串在前
注意:當區分模式時match返回情況有所區別
實例1:"bababa".match(/b(a)/g) // ["ba", "ba", "ba"]
實例2:"bababa".match(/b(a)/) // ["ba", "a", index: 0, input: "bababa"]
search
用法:str.search(Reg)
返回值:Number 位置索引(無匹配返回-1)
實例:"wefeaba".search(/b(a)/) // 5
split
用法:str.split(str)或str.split(Reg) 【自動全局搜索】
返回值:Array 將分開的子字符串放到數組中
實例1:"前端,后端,設計".split(",") // ["前端", "后端", "設計"]
實例2:"f4wef1er2gr".split(/d/) // ["f", "wef", "er", "gr"]
replace
用法:str.replace(str, str)或str.replace(Reg,str)或str.replace(Reg,Fn)
實例1:"前端,后端,設計".replace(",", "|") // "前端|后端,設計"
實例2:"前端,后端,設計".replace(/,/, "|") // "前端|后端,設計"
實例3:"前端,后端,設計".replace(/,/g, "|") // "前端|后端|設計"
實例4:
"前端,后端,設計".replace(/,/g, function($all){ return "{" + $all + "}"; }); // "前端{,}后端{,}設計"
實例5:
"1、這是例子balabala".replace(/1、([u4e00-u9fa5]+)[a-z]*/g, function($all, $1){ return "{" + $1 + "}"; }) // "{這是例子}"
解釋: replace的函數參數順序為-->全匹配,第一捕獲組,第二捕獲組...
4. 由淺入深講解正則邊練習邊寫,你會發現無窮的樂趣,看到中途累了休息一下
最簡單的正則
/a/
用途:匹配a,只要串中包含a即可
說明:js中用兩個/來圈定正則,中間的a即為要匹配的字符
實例:/a/.test("ab") // true
我們現在看一個使用場景,你提供了一個輸入框,這個輸入框是讓用戶輸入手機號,先來個最簡單的規則,用戶的手機號應為11位數字,這是一個最簡單的正則,如下所示。
/^d{11}$/
用途:匹配從開始到結尾共11位數字的字符串
說明:^用來標識開頭,$用來標識結尾,d為數字集合,{11}代表將d循環11次
注意:用來判斷某字符串正確與否一定要加開始結束標識符,看實例2即可看出端倪,十二位數字也被匹配上了,也就是只要串中包含正則可匹配的就能成功,此處可以看出開始結束符的重要性
實例1:/^d{11}$/.test("13212344321") // true
實例2:/d{11}/.test("132123443211") // true
/^d{5,11}$/
用途:匹配從開始到結尾共5-11數字均可的字符串
說明:{5,11} 集合來標識5到11位,可以{5,}來表示5到n多位
實例1:/^d{5,11}$/.test("1234") // false
實例2:/^d{5,11}$/.test("1234567") // true
下面繼續拓展,組合上面方式
/^132d{8}$/
用途:匹配開頭為132的手機號碼
說明:132其實就是直接匹配這三個字符,后面的其實就是動態匹配8位數字,合起來就是11位了
實例1:/^132d{8}$/.test("18912344321") // false
實例2:/^132d{8}$/.test("13212344321") // true
手機號不是只有132開頭的啊,如果我想用189開頭的呢,請看
/^(132|189|133)d{8}$/
用途:匹配開頭為132或189或133的手機號
說明:此處應該注意我們用到了分組()和并列關系|,并列就很簡單了就是說可以132可以189可以133,此處一定注意分組是一定要用的如果不用就會出現實例1的情況,因為并列關系不是前面數字了,變成了三部分了
實例1:/^132|189|133d{8}$/.test("132") // true
實例2:/^(132|189|133)d{8}$/.test("132") // false
實例3:/^(132|189|133)d{8}$/.test("18912344321") // true
實例4:/^(132|189|133)d{8}$/.test("13212344321") // true
現在來看另一個場景,如果我們不是判斷手機號,而是在一堆中文介紹中提取出手機號,那么需要怎么辦呢?
匹配內容:"大家好,我叫jackwang,我的手機號是{13212344321},他的手機號為{13212344321}測試"
/{((132|189|133)d{8})}/
用途:用來匹配文中的手機號,注意手機兩邊有標識{和}我們有這個定位符會很方便將其匹配出來
說明:首先,可以看到{,我們前面提到了{和}為正則特殊字符,雖然此處不加也可以,但是好習慣就是特殊字符要加上避免出問題,例如{1},如果你要匹配的不是前面的東西循環一次那么就會出問題了;另外,看到我用兩個()這相當于有兩個捕獲組,請看實例(這回我用exec,會看的更直接)
實例1:/{((132|189|133)d{8})}/.exec("大家好,我叫jackwang,我的手機號是{13212344321},他的手機號為{13212344321}測試")
// ["{13212344321}", "13212344321", "132", index: 21, input: "大家好,我叫jackwang,我的手機號是{13212344321},他的手機號為{13212344321}測試"]
可以看到第一捕獲組放在了索引為1的位置,我們就可以直接取用了,不過我們會想如果串中如果有多個電話號想搞怎么辦,就像上面這段字符串,下面我給出js寫法,并解釋
var str = "大家好,我叫jackwang,我的手機號是{13212344321},他的手機號為{13212344334}測試"; var reg = /{((132|189|133)d{8})}/g; console.log(reg.exec(str)); console.log(reg.exec(str)); // ["{13212344321}", "13212344321", "132", index: 21, input: "大家好,我叫jackwang,我的手機號是{13212344321},他的手機號為{13212344334}測試"] // ["{13212344334}", "13212344334", "132", index: 41, input: "大家好,我叫jackwang,我的手機號是{13212344321},他的手機號為{13212344334}測試"]
說明:g正則后面加個g表示全局模式;關于模式,i表示不區分大小寫,m表示多行模式,我很少用,此處不講了;對于exec有這么個特性,當正則表達式為全局匹配模式每次執行exec后會刷新下一次執行開始位置,下一次的開始位置為第一次匹配的最后一個字符的下一個位置,所以執行兩次就會將串中所有的匹配出來,這樣就實現了提取的目的
繼續看上面的這段文本,如果我想匹配jackwang怎么辦呢?
/[acgjknw]+/
用途:匹配包含acgjknw這些字符的1或多次循環
說明:[]是字符集,里邊的就是要表示的字符,后面加一個+那么就是表示將前面的[]里邊的循環1次或多次,同理?和*不再用例子展示了
實例:/[acgjknw]+/g.exec("大家好,我叫jackwang,我的手機號是{13212344321},他的手機號為{13212344334}測試")
// ["jackwang", index: 6, input: "大家好,我叫jackwang,我的手機號是{13212344321},他的手機號為{13212344334}測試"]
可以看到我們寫了很多字母,其實我們想匹配英文名,英文名不一定只有這幾個字符,所以此處我們可以這樣
/[a-z]+/
用途:匹配包含a-z的1或多次循環
說明:注意-這是范圍的意思,按照ASCII中的順序,寫這個范圍就行,這回我搞腳本的時候就遇到一個坑,如實例2,本來想匹配:-=,但是忘記對-進行轉義,導致<也被匹配上
實例1:/[a-z]+/g.exec("大家好,我叫jackwang,我的手機號是{13212344321},他的手機號為{13212344334}測試")
// ["jackwang", index: 6, input: "大家好,我叫jackwang,我的手機號是{13212344321},他的手機號為{13212344334}測試"]
實例2:/[:-=]/.test("<")// true
還有一些什么沒講呢,下面多帶帶舉例來說明
貪婪模式/非貪婪模式
字符串:"baeabaeab"
/b[a-z]+b/和/b[a-z]+?b/
說明:前者為貪婪模式,后者為非貪婪模式;請注意+后面的?添加了就為非貪婪模式,同理*和"?"后面可以添加;貪婪模式就是多次循環會盡可能的去匹配,非貪婪模式就是最少匹配,看實例結果即可明白,此正則功能很有用希望大家記住
實例1:/b[a-z]+b/.exec("baeabaeab")
// ["baeabaeab", index: 0, input: "baeabaeab"]
實例2:/b[a-z]+?b/.exec("baeabaeab")
// ["baeab", index: 0, input: "baeabaeab"]
反義
/[^5]/
說明:只要在集合的最開始用^即可,就是表示除了5之外所有字符
實例:/[^5]/.test("5") // false
環視
環視其實某些情況還是挺好用的,還記得前面的匹配手機號嗎?
字符串: "大家好,我叫jackwang,我的手機號是{13212344321},他的手機號為13212344334測試"
其實我們還可以用環視
/(?<={)((132|189|133)d{8})(?=})/
實例:/(?<={)((132|189|133)d{8})(?=})/.exec("大家好,我叫jackwang,我的手機號是{13212344321},他的手機號為13212344334測試")
// ["13212344321", "13212344321", "132", index: 22, input: "大家好,我叫jackwang,我的手機號是{13212344321},他的手機號為13212344334測試"]
說明:剛開始環視可能比較難以理解,我通俗點講,我覺得比我最開始提到的文章好理解
這就像站隊一樣,我在一排中想要找出你來,就可以直接匹配,但是我要找出張三和李四中間的你,但是我只想要你,不要帶著他倆,那么環視就是這個功能
環視被包含的東西是不參與到正則最后匹配出來的東西當中的,它只起到一個定位的作用
(?<={)為逆向肯定環視,舉例來說,在匹配132之前要從1往回看,也就是逆向看看他的上一位是不是{,如果是的話才算合法,如果不是就匹配不成功,也就是你要往前看不是張三,那我就不找你了。同理,(?=})為正向肯定環視,也就是匹配手機號之后,后面一定要有},這樣才算成功,也就是你向后(順序)看是李四才行,這整個表達式也就是你向前(逆向)看必須是張三,向后(正向)看必須是李四,我才會找你。
上面兩個是肯定狀態,另外還有兩個否定狀態,意思就是反的,(?逆向否定環視,(?!pattern)正向否定環視, pattern為要匹配的表達式,舉個例子
/(?
說明:匹配手機號前面沒有{后面沒有}的手機號
實例2:/(?
// ["13212344334", "13212344334", "132", index: 41, input: "大家好,我叫jackwang,我的手機號是{13212344321},他的手機號為13212344334測試"]
綜上,看出來這兩個實例的不同了嗎,當然你可以任意匹配這四種方式來達到你要的效果;但是注意,可能每種語言支持程度不同,不要過度依賴。
5. 其他匹配任意字符建議使用 /[sS]+/因為.會去掉換行符
注意用到的特殊字符一定要轉義(好習慣) /[{}[]^$]/
注意-的使用 /[:-=]/ 這樣會匹配<等,注意轉義
運算符優先級
運算符 | 描述 |
---|---|
轉義 | |
()[] | 圓括號和方括號 |
*, +, ?, {n}, {n,}, {n,m} | 限定符 |
^, $, 任何元字符、任何字符 | 定位點和序列 |
| | 或操作 |
關于那些js的處理函數,自己去摸索吧,篇幅這么長,估計要看不下去了,我搞腳本的時候大量使用了replace和test函數,很好用,對于文件整體處理操作很好用,建議好好學學,請見MDN:https://developer.mozilla.org...
可能還有其他一些沒講到的正則知識,但是上面的這些基本包含了正則的90%了。
總結啰里啰嗦講了這么久,只是為了讓新手能夠由淺入深的慢慢學習,學習正則不是一蹴而就的過程,需要慢慢使用,慢慢探索,同一個匹配可能能寫出好多正則,大家可以慢慢練習,寫出更優雅的正則。
另外要說一點,不是非要寫一個巨長的正則來匹配巨難的字符串,要合理利用各語言的函數來簡化正則的寫法,否則一個巨長的正則可能就是噩夢,這個事自己權衡,相信會將正則用到極致。
謝謝!
本文如有疏漏之處或者又問題交流,請直接回復本文!
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/90013.html
摘要:玩轉對象中的正則表達式的正則表達式語法極大地借鑒了另一種腳本語言的正則表達式語法對象是的一個內置對象,與,類似。創建對象可通過構造函數創建。當要根據用戶輸入來構造正則表達式時,必須采用構造函數方式。如與被看做相同的字符模式。 玩轉javascript RegExp對象 js中的正則表達式 js的正則表達式語法極大地借鑒了另一種腳本語言Perl的正則表達式語法.RegExp對象是js的一...
摘要:在這里使用學而思網校的錄像設備,記錄前端工程師每天學習的內容商城小程序分享人王聰視頻插件開發分享人魏媛視頻原理分享人李佳曉視頻講座優化實戰分享人江芊視頻文件操作分享人張凱視頻一次性學會正則表達式分享人賀杰視頻淺談 在這里使用學而思網校的錄像設備,記錄前端工程師每天學習的內容: 2019-8-22 商城小程序codereview 分享人:王聰 視頻:https://lecture.xue...
摘要:讀這篇文章之前你需要掌握基本的知識,并且有安靜舒適的環境與寬裕的時間,文章有點長,你可以選擇備好或茶來慢慢學習。文章標題有點夸大了,這是一篇正則表達式的入門文章。如有錯誤,歡迎指正。 讀這篇文章之前你需要掌握基本的JavaScript知識,并且有安靜舒適的環境與寬裕的時間,文章有點長,你可以選擇備好coffee或茶來慢慢學習。文章標題有點夸大了,這是一篇正則表達式的入門文章。如有錯誤,...
摘要:即將立秋的課多周刊第期我們的微信公眾號,更多精彩內容皆在微信公眾號,歡迎關注。若有幫助,請把課多周刊推薦給你的朋友,你的支持是我們最大的動力。課多周刊機器人運營中心是如何玩轉起來的分享課多周刊是如何運營并堅持下來的。 即將立秋的《課多周刊》(第2期) 我們的微信公眾號:fed-talk,更多精彩內容皆在微信公眾號,歡迎關注。 若有幫助,請把 課多周刊 推薦給你的朋友,你的支持是我們最大...
閱讀 3794·2021-09-29 09:34
閱讀 3770·2021-09-27 13:34
閱讀 566·2021-09-24 09:47
閱讀 3037·2019-08-30 15:53
閱讀 1808·2019-08-26 13:54
閱讀 2086·2019-08-26 13:43
閱讀 531·2019-08-23 14:47
閱讀 1740·2019-08-23 14:28