鍍金池/ 教程/ HTML/ 正則表達式
瀏覽器端測試:mocha,chai,phantomjs
搭建 Node.js 開發(fā)環(huán)境
測試用例:mocha,should,istanbul
線上部署:heroku
Mongodb 與 Mongoose 的使用
使用 superagent 與 cheerio 完成簡單爬蟲
js 中的那些最佳實踐
使用 eventproxy 控制并發(fā)
使用 promise 替代回調(diào)函數(shù)
作用域與閉包:this,var,(function () {})
持續(xù)集成平臺:travis
測試用例:supertest
benchmark 怎么寫
使用 async 控制并發(fā)
學(xué)習(xí)使用外部模塊
一個最簡單的 express 應(yīng)用
正則表達式
cookie 和 session

正則表達式

目標(biāo)

var web_development = "python php ruby javascript jsonp perhapsphpisoutdated";

找出其中 包含 p 但不包含 ph 的所有單詞,即

[ 'python', 'javascript', 'jsonp' ]

知識點

  1. 正則表達式的使用
  2. js 中的正則表達式與 pcre(http://en.wikipedia.org/wiki/Perl_Compatible_Regular_Expressions ) 的區(qū)別

課程內(nèi)容

開始這門課之前,大家先去看兩篇文章。

《正則表達式30分鐘入門教程》:http://deerchao.net/tutorials/regex/regex.htm

上面這篇介紹了正則表達式的基礎(chǔ)知識,但是對于零寬斷言沒有展開來講,零寬斷言看下面這篇:

《正則表達式之:零寬斷言不『消費』》:http://fxck.it/post/50558232873

好了。

在很久很久以前,有一門語言一度是字符串處理領(lǐng)域的王者,叫 perl。

伴隨著 perl,有一個類似正則表達式的標(biāo)準(zhǔn)被實現(xiàn)了出來,叫 pcre:Perl Compatible Regular Expressions。

不遺憾的是,js 里面的正則與 pcre 不是兼容的。很多語言都這樣。

如果需要測試你自己寫的正則表達式,建議上這里:http://refiddle.com/ ,可以所見即所得地調(diào)試。

接下來我們主要講講 js 中需要注意的地方,至于正則表達式的內(nèi)容,上面那兩篇文章足夠?qū)W習(xí)了。

第一,

js 中,對于四種零寬斷言,只支持 零寬度正預(yù)測先行斷言 和 零寬度負預(yù)測先行斷言 這兩種。

第二,

js 中,正則表達式后面可以跟三個 flag,比如 /something/igm。

他們的意義分別是,

  • i 的意義是不區(qū)分大小寫
  • g 的意義是,匹配多個
  • m 的意義是,是 ^$ 可以匹配一行的開頭。

分別舉個例子:

/a/.test('A') // => false
/a/i.test('A') // => true

'hello hell hoo'.match(/h.*?\b/) // => [ 'hello', index: 0, input: 'hello hell hoo' ]
'hello hell hoo'.match(/h.*?\b/g) // => [ 'hello', 'hell', 'hoo' ]

'aaa\nbbb\nccc'.match(/^[\s\S]*?$/g) // => [ 'aaa\nbbb\nccc' ]
'aaa\nbbb\nccc'.match(/^[\s\S]*?$/gm) // => [ 'aaa', 'bbb', 'ccc' ]

與 m 意義相關(guān)的,還有 \A, \Z\z

他們的意義分別是:

\A  字符串開頭(類似^,但不受處理多行選項的影響)
\Z  字符串結(jié)尾或行尾(不受處理多行選項的影響)
\z  字符串結(jié)尾(類似$,但不受處理多行選項的影響)

在 js 中,g flag 會影響 String.prototype.match()RegExp.prototype.exec() 的行為

String.prototype.match() 中,返回數(shù)據(jù)的格式會不一樣,加 g 會返回數(shù)組,不加 g 則返回比較詳細的信息

> 'hello hell'.match(/h(.*?)\b/g)
[ 'hello', 'hell' ]

> 'hello hell'.match(/h(.*?)\b/)
[ 'hello',
  'ello',
  index: 0,
  input: 'hello hell' ]

RegExp.prototype.exec() 中,加 g 之后,如果你的正則不是字面量的正則,而是存儲在變量中的話,特么的這個變量就會變得有記憶??!

> /h(.*?)\b/g.exec('hello hell')
[ 'hello',
  'ello',
  index: 0,
  input: 'hello hell' ]
> /h(.*?)\b/g.exec('hello hell')
[ 'hello',
  'ello',
  index: 0,
  input: 'hello hell' ]

> var re = /h(.*?)\b/g;
undefined
> re.exec('hello hell')
[ 'hello',
  'ello',
  index: 0,
  input: 'hello hell' ]
> re.exec('hello hell')
[ 'hell',
  'ell',
  index: 6,
  input: 'hello hell' ]
>

第三,

大家知道,. 是不可以匹配 \n 的。如果我們想匹配的數(shù)據(jù)涉及到了跨行,比如下面這樣的。

var multiline = require('multiline');

var text = multiline.stripIndent(function () {
/*
    head
code code2 .code3```
```
foot

*/ });


如果我們想把兩個 \`\`\` 中包含的內(nèi)容取出來,應(yīng)該怎么辦?

直接用 `.` 匹配不到 `\n`,所以我們需要找到一個原子,能匹配包括 `\n` 在內(nèi)的所有字符。

這個原子的慣用寫法就是 `[\s\S]`

var match1 = text.match(/^[\s\S]+?^/gm); console.log(match1) // => [ '\ncode code2 code3\n```' ]

// 這里有一種很騷的寫法,[^] 與 [\s\S] 等價 var match2 = text.match(/^[^]+?^/gm) console.log(match2) // => [ '\ncode code2 .code3\n```' ]



完。