正則表達式是一個描述字符模式的對象。
JavaScript
的
RegExp
對象和
String
對象定義了使用正則表達式來執行強大的模式匹配和文本檢索與替換函數的方法
.
'***********************
'??????????????\\JavaScript//
'
'***********************
在
JavaScript
中
,
正則表達式是由一個
RegExp
對象表示的
.
當然
,
可以使用一個
RegExp()
構造函數來創建
RegExp
對象
,
也可以用
JavaScript?1.2
中的新添加的一個特殊語法來創建
RegExp
對象
.
就像字符串直接量被定義為包含在引號內的字符一樣
,
正則表達式直接量也被定義為包含在一對斜杠
(/)
之間的字符
.
所以
,JavaScript
可能會包含如下的代碼
:
var?pattern?=?/s$/;
這行代碼創建一個新的
RegExp
對象
,
并將它賦給變量
parttern.
這個特殊的
RegExp
對象和所有以字母
"e;s"e;
結尾的字符串都匹配
.
用
RegExp()
也可以定義
一個等價的正則表達式
,
代碼如下
:
var?pattern?=?new?RegExp("e;s$"e;);
無論是用正則表達式直接量還是用構造函數
RegExp(),
創建一個
RegExp
對象都是比較容易的
.
較為困難的任務是用正則表達式語法來描述字符的模式
.
JavaScript
采用的是
Perl
語言正則表達式語法的一個相當完整的子集
.
正則表達式的模式規范是由一系列字符構成的
.
大多數字符
(
包括所有字母數字字符
)
描述的都是按照字面意思進行匹配的字符
.
這樣說來
,
正則表達式
/java/
就和
所有包含子串
?"e;java"e;?
的字符串相匹配
.
雖然正則表達式中的其它字符不是按照字面意思進行匹配的
,
但它們都具有特殊的意義
.
正則表達式
?/s$/?
包含兩個字符
.
第一個特殊字符
?"e;s"e;?
是按照字面意思與自身相匹配
.
第二個字符
?"e;$"e;?
是一個特殊字符
,
它所匹配的是字符串的結尾
.
所以正則表達式
?/s$/?
匹配的就是以字母
?"e;s"e;?
結尾
的字符串
.
1.
直接量字符
我們已經發現了
,
在正則表達式中所有的字母字符和數字都是按照字面意思與自身相匹配的
.JavaScript
的正則表達式還通過以反斜杠
(\)
開頭的轉義序列支持某些非字母字符
.
例如
,
序列
?"e;\n"e;?
在字符串中匹配的是一個直接量換行符
.
在正則表達式中
,
許多標點符號都有特殊的含義
.
下面是這些字符和它們的含義
:
正則表達式的直接量字符
字符
??????????????????????????????????
匹配
________________________________
字母數字字符
???????????????????????
自身
\?f???????????????????????????????????????
換頁符
\?n??????????????????????????????????????
換行符
\?r???????????????????????????????????????
回車
\?t???????????????????????????????????????
制表符
\?v??????????????????????????????????????
垂直制表符
\?/???????????????????????????????????????
一個
?/?
直接量
\?\???????????????????????????????????????
一個
?\?
直接量
\?.???????????????????????????????????????
一個
?.?
直接量
\?*??????????????????????????????????????
一個
?*?
直接量
\?+??????????????????????????????????????
一個
?+?
直接量
\?????????????????????????????????????????
一個
???
直接量
\?|????????????????????????????????????????
一個
?|?
直接量
\?(????????????????????????????????????????
一個
?(?
直接量
\?)????????????????????????????????????????
一個
?)?
直接量
\?[????????????????????????????????????????
一個
?[?
直接量
\?]????????????????????????????????????????
一個
?]?
直接量
\?{????????????????????????????????????????
一個
?{?
直接量
\?}????????????????????????????????????????
一個
?}?
直接量
\?XXX????????????????????????????????????
由十進制數
?XXX?
指
?
定的
ASCII
碼字符
\?Xnn????????????????????????????????????
由十六進制數
?nn?
指定的
ASCII
碼字符
\?cX???????????????????????????????????????
控制字符
^X.?
例如
,?\cI
等價于
?\t,?\cJ
等價于
?\n
___________________________________________________
如果想在正則表達式中使用特殊的標點符號
,
必須在它們之前加上一個
?"e;\"e;?.
2.
字符類
將單獨的直接符放進中括號內就可以組合成字符類
.
一個字符類和它所包含的任何一個字符都匹配
,
所以正則表達式
?/?[abc]?/?
和字母
?"e;a"e;?,?"e;b"e;?,?"e;c"e;?
中的任何一個
都匹配
.
另外還可以定義否定字符類
,
這些類匹配的是除那些包含在中括號之內的字符外的所有字符
.
定義否定字符尖時
,
要將一個
?^?
符號作為從左中括號算起的第
一個字符
.
正則表達式的集合是
?/?[a-zA-z0-9]?/?.
由于某些字符類非常常用
,
所以
JavaScript
的正則表達式語法包含一些特殊字符和轉義序列來表示這些常用的類
.
例如
,??\s?
匹配的是空格符
,
制表符和其它空白符
,?\s
匹配的則是空白符之外的任何字符
.
正則表灰式的字符類
字符
??????????????????????????????????????????
匹配
____________________________________________________
[...]???????????????????????????????????????????
位于括號之內的任意字符
[^...]?????????????????????????????????????????
不在括號之中的任意字符
?
.????????????????????????????????????????????????
除了換行符之外的任意字符
,
等價于
[^\n]
\w?????????????????????????????????????????????
任何單字字符
,?
等價于
[a-zA-Z0-9]
\W????????????????????????????????????????????
任何非單字字符
,
等價于
[^a-zA-Z0-9]
\s??????????????????????????????????????????????
任何空白符
,
等價于
[\?t?\?n?\?r?\?f?\?v]
\S??????????????????????????????????????????????
任何非空白符
,
等價于
[^\?t?\?n?\?r?\?f?\?v]
\d??????????????????????????????????????????????
任何數字
,
等價于
[0-9]
\D??????????????????????????????????????????????
除了數字之外的任何字符
,
等價于
[^0-9]
[\b]????????????????????????????????????????????
一個退格直接量
(
特例
)
________________________________________________________________
3.
復制
用以上的正則表式的語法
,
可以把兩位數描述成
??/?\?d?\?d?/,
把四位數描述成
?/?\d?\?d?\?d?\?d?/.
但我們還沒有一種方法可以用來描述具有任意多數位的數字或者是一個字符串
.
這個串由三個字符以及跟隨在字母之后的一位數字構成
.
這些復雜的模式使用的正則表達式語法指定了該表達式中每個元素要重復出現的次數
.
指定復制的字符總是出現在它們所作用的模式后面
.
由于某種復制類型相當常用
.
所以有一些特殊的字符專門用于表示它們
.
例如
:?+
號匹配的就是復制前一模式一次或多次的
模式
.
下面的表列出了復制語法
.
先看一個例子
:
/\d{2,?4}/??????????????????????????????????//
匹配
2
到
4
間的數字
.
/\w{3}?\d?/???????????????????????????????//
匹配三個單字字符和一個任意的數字
.
/\s+java\s+/?????????????????????????????//
匹配字符串
"e;java"e;?,
并且該串前后可以有一個或多個空格
.
/[^"e;]?*?/???????????????????????????????????//
匹配零個或多個非引號字符
.
正則表達式的復制字符
字符
??????????????????????????????????????????
含義
__________________________________________________________________
{n,?m}???????????????????????????????????????
匹配前一項至少
n
次
,
但是不能超過
m
次
{n,?}??????????????????????????????????????????
匹配前一項
n
次
,
或者多次
{n}????????????????????????????????????????????
匹配前一項恰好
n
次
????????????????????????????????????????????????
匹配前一項
0
次或
1
次
,
也就是說前一項是可選的
.?
等價于
?{0,?1}
+??????????????????????????????????????????????
匹配前一項
1
次或多次
,
等價于
{1,}
*???????????????????????????????????????????????
匹配前一項
0
次或多次
.
等價于
{0,}
___________________________________________________________________
4.
選擇
,
分組和引用
?
正則表達式的語法還包括指定選擇項
,
對子表達式分組和引用前一子表達式的特殊字符
.
字符
|?
用于分隔供選擇的字符
.
例如
:?/ab|cd|ef/?
匹配的是字符串
?"e;ab"e;,
或者是字符串
?"e;cd"e;,
又
或者
?"e;ef"e;.?/\d{3}|[a-z]{4}/?
匹配的是要么是一個三位數
,
要么是四個小寫字母
.
在正則表達式中括號具有幾種作用
.
它的主要作用是把單獨的項目分組成子表達式
,
以便可以像處理一個獨立的單元那種用
?*
、
+
或
??
來處理那些項目
.
例如
:?/java(script)??/?
匹配的是
字符串
?"e;java"e;,
其后既可以有
?"e;script"e;,
也可以沒有
.?/?(ab|cd)?+?|ef)?/?
匹配的既可以是字符串
?"e;ef"e;,
也可以是字符串
"e;ab"e;?
或者
?"e;cd"e;?
的一次或多次重復
.
在正則表達式中
,
括號的第二個用途是在完整的模式中定義子模式。當一個正則表達式成功地和目標字符串相匹配時
,
可以從目標串中抽出和括號中的子模式相匹配的部分
.
例如
,
假定
我們正在檢索的模式是一個或多個字母后面跟隨一位或多位數字
,
那么我們可以使用模式
?/?[a-z]?+?\?d+/.
但是由于假定我們真正關心的是每個匹配尾部的數字
,
那么如果我們將模式的
數字部分放在括號中
?(/?[a-z]?+?(\d+)/)?,
我們就可以從所檢索到的任何匹配中抽取數字了
,
之后我們會對此進行解析的
.
代括號的子表達式的另一個用途是
,
允許我們在同一正則表達式的后面引用前面的子表達式
.
這是通過在字符串
?\?
后加一位或多位數字來實現的
.
數字指的是代括號的子表達式在正則表達
式中的位置
.
例如
:?\1?
引用的是第一個代括號的子表達式
.?\3?
引用的是第三個代括號的子表達式
.
注意
,
由于子表達式可以嵌套在其它子表達式中
,
所以它的位置是被計數的左括號的位置
.
例如
:
在下面的正則表達式被指定為
?\2:
?????????????????????????????????????????????????????????????????/([Jj]ava([Ss]cript))?\sis?\s?(fun\w*)?/
對正則表達式中前一子表達式的引用所指定的并不是那個子表達式的模式
,
而是與那個模式相匹配的文本
.
這樣
,
引用就不只是幫助你輸入正則表達式的重復部分的快捷方式了
,
它還實施了
一條規約
,
那就是一個字符串各個分離的部分包含的是完全相同的字符
.
例如
:
下面的正則表達式匹配的就是位于單引號或雙引號之內的所有字符
.
但是
,
它要求開始和結束的引號匹配
(
例如
兩個都是雙引號或者都是單引號
):
????????????????????????????????????????????????????????????????/['?"e;]?[^?'?"e;]*['?"e;]/
如果要求開始和結束的引號匹配
,
我們可以使用如下的引用
:
??????????????????????????????????????????????????????????????????????????????????????????????????????????/(?['?"e;]?)?[^?'?"e;]?*?\1/
\1
匹配的是第一個代括號的子表達式所匹配的模式
.
在這個例子中
,
它實施了一種規約
,
那就是開始的引號必須和結束的引號相匹配
.
注意
,
如果反斜杠后跟隨的數字比代括號的子表達式數多
,
那么它就會被解析為一個十進制的轉義序列
,
而不是一個引用
.
你可以堅持使用完整的三個字符來表示轉義序列
,
這們就可以避免混淆了
.
例如
,
使用
?\044,
而不是
\44.
下面是正則表達式的選擇、分組和引用字符
:
字符
?????????????????????????????????????????????????????
含義
____________________________________________________________________
|???????????????????????????????????????????????????????????
選擇
.
匹配的要么是該符號左邊的子表達式
,
要么它右邊的子表達式
(...)????????????????????
分組
.
將幾個項目分為一個單元
.
這個單元可由
?*
、
+
、?和
|
等符號使用
,
而且還可以記住和這個組匹配的字符以供此后引用使用
\n?????????????????????????????????????????????????????????
和第
n
個分組所匹配的字符相匹配
.
分組是括號中的子表達式
(
可能是嵌套的
).
分組號是從左到右計數的左括號數
____________________________________________________________________
5.
指定匹配的位置
我們已經看到了
,
一個正則表達式中的許多元素才能夠匹配字符串的一個字符
.
例如
:?\s?
匹配的只是一個空白符
.
還有一些正則表達式的元素匹配的是字符之間寬度為
0
的空間
,
而不是實際的字符
例如
:?\b?
匹配的是一個詞語的邊界
,
也就是處于一個
/w
字字符和一個
\w
非字字符之間的邊界
.
像
\b?
這樣的字符并不指定任何一個匹配了的字符串中的字符
,
它們指定的是匹配所發生的合法位置
.
有時我們稱這些元素為正則表達式的錨
.
因為它們將模式定位在檢索字符串中的一個特定位置
.
最常用的錨元素是
?^,?
它使模式依賴于字符串的開頭
,
而錨元素
$
則使模式定位在字符串的末尾
.
例如
:
要匹配詞
?"e;javascript"e;?,
我們可以使用正則表達式
?/^?javascript?$/.?
如果我們想檢索
?"e;java"e;?
這個詞自身
?(
不像在
?"e;javascript"e;?
中那樣作為前綴
),
那么我們可以使用模式
?/\s?java?\s?/,?
它要求
在詞語
java
之前和之后都有空格
.
但是這樣作有兩個問題
.
第一
:?
如果
?"e;java"e;?
出現在一個字符的開頭或者是結尾
.
該模式就不會與之匹配
,
除非在開頭和結尾處有一個空格
.?
第二
:?
當這個模式找到
一個與之匹配的字符時
,
它返回的匹配的字符串前端和后端都有空格
,
這并不是我們想要的
.
因此
,
我們使用詞語的邊界
?\b?
來代替真正的空格符
?\s?
進行匹配
.?
結果表達式是
?/\b?java?\b/.
下面是正則表達式的錨字符
:
字符
???????????????????????????????????????????????????????
含義
____________________________________________________________________
^??????????????????????????????????????????????????????????
匹配的是字符的開頭
,
在多行檢索中
,
匹配的是一行的開頭
$??????????????????????????????????????????????????????????
匹配的是字符的結尾
,
在多行檢索中
,
匹配的是一行的結尾
\b?????????????????????????????????????????????????????????
匹配的是一個詞語的邊界
.
簡而言之就是位于字符
\w?
和
?\w
之間的位置
(
注意
:[\b]??????????????????????????????????????????????????????
匹配的是退格符
)
\B?????????????????????????????????????????????????????????
匹配的是非詞語的邊界的字符
_____________________________________________________________________
6.
屬性
有關正則表達式的語法還有最后一個元素
,
那就是正則表達式的屬性
,
它說明的是高級模式匹配的規則
.
和其它正則表達式語法不同
,
屬性是在
?/?
符號之外說明的
.
即它們不出現在兩個斜杠之間
,
而是位于
第二個斜杠之后
.javascript?1.2
支持兩個屬性
.
屬性
?i?
說明模式匹配應該是大小寫不敏感的
.
屬性
?g?
說明模式匹配應該是全局的
.
也就是說
,
應該找出被檢索的字符串中所有的匹配
.
這兩種屬性聯合起來就
可以執行一個全局的
,
大小寫不敏感的匹配
.
例如
:?
要執行一個大小不敏感的檢索以找到詞語
?"e;java"e;?(
或者是
?"e;java"e;?
、
"e;JAVA"e;
等
)?
的第一個具體值
,
我們可以使用大小不敏感的正則表達式
?/\b?java\b/i?.
如果要在一個字符串中找到
?"e;java"e;?
所有的具體
值
,
我們還可以添加屬性
?g,?
即
?/\b?java?\b/gi?.
以下是正則表達式的屬性
:
字符
??????????????????????????????????????????????????????
含義
_________________________________________
i???????????????????????????????????
執行大小寫不敏感的匹配
g??????????????????????????????????
執行一個全局的匹配
,
簡而言之
,
就是找到所有的匹配
,
而不是在找到第一個之后就停止了
_________________________________________
除屬性
?g?
和
?i?
之外
,
正則表達式就沒有其它像屬性一樣的特性了
.
如果將構造函數
?RegExp?
的靜態屬性
?multiline?
設置為
?true?,
那么模式匹配將以多行的模式進行
.
在這種模式下
,
錨字符
?^?
和
?$?
匹配的不只是檢
索字符串的開頭和結尾
,
還匹配檢索字符串內部的一行的開頭和結尾
.
例如
:?
模式
?/Java$/?
匹配的是
?"e;Java"e;,
但是并不匹配
?"e;Java\nis?fun"e;?.
如果我們設置了
?multiline?
屬性
,
那么后者也將被匹配
:RegExp.multiline?=?true;
?