正規表示式及多語言操作指南
1. 正規表示式
正規表示式是對字串操作的一種邏輯公式,就是用事先定義好的一些特定字元、及這些特定字元的組合,組成一個“規則字串”,這個“規則字串”用來表達對字串的一種過濾邏輯。
正規表示式是對字串(包括普通字元(例如,a 到 z 之間的字母)和特殊字元(稱為“元字元”))操作的一種邏輯公式,就是用事先定義好的一些特定字元、及這些特定字元的組合,組成一個“規則字串”,這個“規則字串”用來表達對字串的一種過濾邏輯。正規表示式是一種文字模式,模式描述在搜尋文字時要匹配的一個或多個字串。
1.1 正規表示式符號
1.1.1 符號類
通用的符號:
符號 | 含義 | 範例 |
---|---|---|
. | 任意字元 | “A”, “ ”(空格), “囧”, “1” |
d | 匹配一個數字字元。等價於[0-9] | “1”, “2”, “3” |
D | 匹配一個非數字字元。等價於[^0-9] | “a”, “b”, “c” |
w | 匹配包括下劃線的任何單詞字元。等價於“[A-Za-z0-9_]” | “Y”, “x”, “_”, “9” |
W | 匹配任何非單詞字元。等價於“[^A-Za-z0-9_]” | “ ”(空格) |
s | 匹配任何空白字元,包括空格、製表符、換頁符等等。等價於[ fnrtv] | “ ”(空格), “r”, “t”, “n” |
S | 匹配任何非空白字元。等價於[^fnrtv] | “B”, “囧”, “5” |
特殊的符號:
符號 | 含義 | 範例 |
---|---|---|
r | 匹配一個回車符。等價於x0d和cM | |
f | 匹配一個換頁符。等價於x0c和cL | |
n | 匹配一個換行符。等價於x0a和cJ | |
t | 匹配一個製表符。等價於x09和cI | |
\ | 匹配 | “” |
xhh | 以ASCII碼進⾏匹配 | x41可以匹配”A” |
uhhhh | 以UNICODE碼進⾏匹配 | u4e00-u9fa5 中⽂的範圍 |
重點:關於 .
單行模式下(gs
):能匹配
多行模式下(gm
):不能匹配
1.1.2 字符集合
符號 | 含義 |
---|---|
[a-z] | 字元範圍。匹配指定範圍內的任意字元。例如,“[a-z]”可以匹配“a”到“z”範圍內的任意小寫字母字元 |
[abc] | 字符集合。匹配所包含的任意一個字元。例如,“[abc]”可以匹配“plain”中的“a” |
[^xyz] | 負值字符集合。匹配未包含的任意字元。例如,“1”可以匹配“plain”中的“p” |
[^a-c] | 負值字元範圍。匹配任何不在指定範圍內的任意字元。例如,“2”可以匹配任何不在“a”到“z”範圍內的任意字元 |
[-] | 匹配 “-” |
1.1.3 字元邊界
符號 | 含義 |
---|---|
^ | 匹配輸入字串的開始位置。如果設定了RegExp物件的Multiline屬性,^也匹配“n”或“r”之後的位置 |
& | 匹配輸入字串的結束位置。如果設定了RegExp物件的Multiline屬性,$也匹配“n”或“r”之前的位置 |
匹配一個單詞邊界,也就是指單詞和空格間的位置。例如,“erb”可以匹配“never”中的“er”,但不能匹配“verb”中的“er” | |
B | 匹配非單詞邊界。“erB”能匹配“verb”中的“er”,但不能匹配“never”中的“er” |
1.1.4 數量界定符
符號 | 定義 |
---|---|
x{n} | n是一個非負整數。匹配確定的n次。例如,“o{2}”不能匹配“Bob”中的“o”,但是能匹配“food”中的兩個o |
x{n,} | n是一個非負整數。至少匹配n次。例如,“o{2,}”不能匹配“Bob”中的“o”,但能匹配“foooood”中的所有o。“o{1,}”等價於“o+”。“o{0,}”則等價於“o*” |
x{n,m} | m和n均為非負整數,其中n<=m。最少匹配n次且最多匹配m次。例如,“o{1,3}”將匹配“fooooood”中的前三個o。“o{0,1}”等價於“o?”。請注意在逗號和兩個數之間不能有空格 |
x* | 匹配前面的子表示式零次或多次。例如,zo*能匹配“z”以及“zoo”。*等價於{0,} |
x+ | 匹配前面的子表示式一次或多次。例如,“zo+”能匹配“zo”以及“zoo”,但不能匹配“z”。+等價於{1,} |
x? | 匹配前面的子表示式零次或一次。例如,“do(es)?”可以匹配“does”或“does”中的“do”。?等價於{0,1} |
重點:關於 ?
貪婪模式下:數量限定符都是在滿⾜條件下儘可能的匹配更多的字元
非貪婪模式下:如果希望在滿⾜條件下儘可能少的匹配字元, 在數量限定符後⾯加上“?”
1.1.5 分支條件
符號 | 定義 | |||
---|---|---|---|---|
x | y | 匹配x或y。例如,“z | food”能匹配“z”或“food”。“(z | f)ood”則匹配“zood”或“food”。 |
1.1.6 分組與後向引⽤
符號 | 定義 | |||
---|---|---|---|---|
(x) | 匹配pattern並獲取這一匹配。所獲取的匹配可以從產生的Matches集合得到,在VBScript中使用SubMatches集合,在JScript中則使用$0…$9屬性。要匹配圓括號字元,請使用“(”或“)” | |||
1..n | 引⽤第1-n組匹配 | |||
(?:x) | 匹配pattern但不獲取匹配結果,也就是說這是一個非獲取匹配,不進行儲存供以後使用。這在使用或字元“( | )”來組合一個模式的各個部分是很有用。例如“industr(?:y | ies)”就是一個比“industry | industries”更簡略的表示式 |
1.1.7 斷⾔
符號 | 定義 | |||
---|---|---|---|---|
(?=pattern) | 正向肯定預查,在任何匹配pattern的字串開始處匹配查詢字串。這是一個非獲取匹配,也就是說,該匹配不需要獲取供以後使用。例如,“Windows(?=95 | 98 | NT | 2000)”能匹配“Windows2000”中的“Windows”,但不能匹配“Windows3.1”中的“Windows”。預查不消耗字元,也就是說,在一個匹配發生後,在最後一次匹配之後立即開始下一次匹配的搜尋,而不是從包含預查的字元之後開始 |
(?!pattern) | 正向否定預查,在任何不匹配pattern的字串開始處匹配查詢字串。這是一個非獲取匹配,也就是說,該匹配不需要獲取供以後使用。例如“Windows(?!95 | 98 | NT | 2000)”能匹配“Windows3.1”中的“Windows”,但不能匹配“Windows2000”中的“Windows”。預查不消耗字元,也就是說,在一個匹配發生後,在最後一次匹配之後立即開始下一次匹配的搜尋,而不是從包含預查的字元之後開始 |
(?<=pattern) | 反向肯定預查,與正向肯定預查類擬,只是方向相反。例如,“(?<=95 | 98 | NT | 2000)Windows”能匹配“2000Windows”中的“Windows”,但不能匹配“3.1Windows”中的“Windows” |
(?<!pattern) | 反向否定預查,與正向否定預查類擬,只是方向相反。例如“(?<!95 | 98 | NT | 2000)Windows”能匹配“3.1Windows”中的“Windows”,但不能匹配“2000Windows”中的“Windows” |
1.2 正規表示式網站
以下是常用的一些線上正規表示式測試工具,其中個人感覺第一個最好!
- http://regex101.com/
- http://regexr.com/
- http://tool.lu/regex/
- http://tool.oschina.net/regex/
- http://tool.chinaz.com/regex/
1.3 正規表示式工具
1.4 常用的正規表示式
需求 | 正規表示式 | ||||
---|---|---|---|---|---|
使用者名稱 | ^[a-z0-9_-]{3,16}$ | ||||
密碼 | ^[a-z0-9_-]{6,18}$ | ||||
十六進位制值 | ^#?([a-f0-9]{6} | [a-f0-9]{3})$ | |||
電子郵箱 | ^([a-z0-9_.-]+)@([da-z.-]+).([a-z.]{2,6})$/ | ||||
URL | ^(https?://)?([da-z.-]+).([a-z.]{2,6})([/w .-]*)*/?$ | ||||
IP 地址 | /((2[0-4]d | 25[0-5] | [01]?dd?).){3}(2[0-4]d | 25[0-5] | [01]?dd?)/ |
/^(?:(?:25[0-5] | 20-4 | [01]?0-9?).){3}(?:25[0-5] | 20-4 | [01]?0-9?)$/</div> | |
HTML 標籤 | ^<([a-z]+)([^<]+)*(?:>(.*)</1> | s+/>)$ | |||
刪除程式碼註釋 | (?<!http: | S)//.*$ | |||
Unicode編碼中的漢字範圍 | ^[u2E80-u9FFF]+$ | ||||
一個單詞連續出現的位置 | b([a-z]+) 1b/gi | ||||
匹配空行 | ^s*$ | ||||
匹配中文字元 | [u4e00-u9fa5] | ||||
匹配雙位元組字元(包括漢字在內) | [^x00-xff] | ||||
匹配空白行 | ns*r | ||||
匹配國內電話號碼 | d{3}-d{8} | d{4}-{7,8} | |||
匹配騰訊QQ號 | 1-9{4,} | ||||
匹配中國郵政編碼 | [1-9]d{5}(?!d) | ||||
匹配18位身份證號 | ^(d{6})(d{4})(d{2})(d{2})(d{3})([0-9] | X)$ | |||
匹配(年-月-日)格式日期 | ([0-9]{3}[1-9] | ||||
匹配正浮點數 | ^[1-9]d*.d* | 0.d*[1-9]d*$ | |||
匹配負浮點數 | ^-[1-9]d*.d* | -0.d*[1-9]d*$ |
2. Python操作正規表示式
2.1 匹配字串
Python提供re
模組,包含所有正規表示式的功能。由於Python的字串本身也用轉義,所以要特別注意:
s = `ABC\-001` # Python的字串
# 對應的正規表示式字串變成:
# `ABC-001`
因此我們強烈建議使用Python的r
字首,就不用考慮轉義的問題了:
s = r`ABC-001` # Python的字串
# 對應的正規表示式字串不變:
# `ABC-001`
先看看如何判斷正規表示式是否匹配:
>>> import re
>>> re.match(r`^d{3}-d{3,8}$`, `010-12345`)
<_sre.SRE_Match object; span=(0, 9), match=`010-12345`>
>>> re.match(r`^d{3}-d{3,8}$`, `010 12345`)
>>>
match()
方法判斷是否匹配,如果匹配成功,返回一個Match
物件,否則返回None
。常見的判斷方法就是:
test = `使用者輸入的字串`
if re.match(r`正規表示式`, test):
print(`ok`)
else:
print(`failed`)
2.2 切分字串
用正規表示式切分字串比用固定的字元更靈活,請看正常的切分程式碼:
>>> `a b c`.split(` `)
[`a`, `b`, ``, ``, `c`]
嗯,無法識別連續的空格,用正規表示式試試:
>>> re.split(r`s+`, `a b c`)
[`a`, `b`, `c`]
無論多少個空格都可以正常分割。加入,
試試:
>>> re.split(r`[s,]+`, `a,b, c d`)
[`a`, `b`, `c`, `d`]
再加入;
試試:
>>> re.split(r`[s,;]+`, `a,b;; c d`)
[`a`, `b`, `c`, `d`]
如果使用者輸入了一組標籤,下次記得用正規表示式來把不規範的輸入轉化成正確的陣列。
2.3 分組
除了簡單地判斷是否匹配之外,正規表示式還有提取子串的強大功能。用()
表示的就是要提取的分組(Group)。比如:
^(d{3})-(d{3,8})$
分別定義了兩個組,可以直接從匹配的字串中提取出區號和本地號碼:
>>> m = re.match(r`^(d{3})-(d{3,8})$`, `010-12345`)
>>> m
<_sre.SRE_Match object; span=(0, 9), match=`010-12345`>
>>> m.group(0)
`010-12345`
>>> m.group(1)
`010`
>>> m.group(2)
`12345`
如果正規表示式中定義了組,就可以在Match
物件上用group()
方法提取出子串來。
注意到group(0)
永遠是原始字串,group(1)
、group(2)
……表示第1、2、……個子串。
提取子串非常有用。來看一個更凶殘的例子:
>>> t = `19:05:30`
>>> m = re.match(r`^(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])$`, t)
>>> m.groups()
(`19`, `05`, `30`)
這個正規表示式可以直接識別合法的時間。但是有些時候,用正規表示式也無法做到完全驗證,比如識別日期:
`^(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`
這樣的非法日期,用正則還是識別不了,或者說寫出來非常困難,這時就需要程式配合識別了。
2.4 貪婪匹配
最後需要特別指出的是,正則匹配預設是貪婪匹配,也就是匹配儘可能多的字元。舉例如下,匹配出數字後面的0
:
>>> re.match(r`^(d+)(0*)$`, `102300`).groups()
(`102300`, ``)
由於d+
採用貪婪匹配,直接把後面的0
全部匹配了,結果0*
只能匹配空字串了。
必須讓d+
採用非貪婪匹配(也就是儘可能少匹配),才能把後面的0
匹配出來,加個?
就可以讓d+
採用非貪婪匹配:
>>> re.match(r`^(d+?)(0*)$`, `102300`).groups()
(`1023`, `00`)
2.5 編譯
當我們在Python中使用正規表示式時,re模組內部會幹兩件事情:
- 編譯正規表示式,如果正規表示式的字串本身不合法,會報錯;
- 用編譯後的正規表示式去匹配字串。
如果一個正規表示式要重複使用幾千次,出於效率的考慮,我們可以預編譯該正規表示式,接下來重複使用時就不需要編譯這個步驟了,直接匹配:
>>> import re
# 編譯:
>>> re_telephone = re.compile(r`^(d{3})-(d{3,8})$`)
# 使用:
>>> re_telephone.match(`010-12345`).groups()
(`010`, `12345`)
>>> re_telephone.match(`010-8086`).groups()
(`010`, `8086`)
編譯後生成Regular Expression物件,由於該物件自己包含了正規表示式,所以呼叫對應的方法時不用給出正則字串。
3. Java操作正規表示式
3.1 基礎
Java提供了java.util.regex
包來操作正規表示式,主要包含以下三個類:
-
Pattern
類:pattern 物件是一個正規表示式的編譯表示。Pattern 類沒有公共構造方法。要建立一個 Pattern 物件,你必須首先呼叫其公共靜態編譯方法,它返回一個 Pattern 物件。該方法接受一個正規表示式作為它的第一個引數。 -
Matcher
類:Matcher 物件是對輸入字串進行解釋和匹配操作的引擎。與Pattern 類一樣,Matcher 也沒有公共構造方法。你需要呼叫 Pattern 物件的 matcher 方法來獲得一個 Matcher 物件。 -
PatternSyntaxException
:PatternSyntaxException 是一個非強制異常類,它表示一個正規表示式模式中的語法錯誤。
以下例項中使用了正規表示式 .*runoob.* 用於查詢字串中是否包了 runoob 子串:
import java.util.regex.*;
class RegexExample1{
public static void main(String args[]){
String content = "I am noob " +
"from runoob.com.";
String pattern = ".*runoob.*";
boolean isMatch = Pattern.matches(pattern, content);
System.out.println("字串中是否包含了 `runoob` 子字串? " + isMatch);
}
}
輸出:
字串中是否包含了 `runoob` 子字串? true
3.2 捕獲組
捕獲組是把多個字元當一個單獨單元進行處理的方法,它通過對括號內的字元分組來建立。
例如,正規表示式 (dog) 建立了單一分組,組裡包含”d”,”o”,和”g”。
捕獲組是通過從左至右計算其開括號來編號。例如,在表示式((A)(B(C)))
,有四個這樣的組:
((A)(B(C)))
(A)
(B(C))
(C)
可以通過呼叫 matcher 物件的 groupCount 方法來檢視錶達式有多少個分組。groupCount 方法返回一個 int 值,表示matcher物件當前有多個捕獲組。
還有一個特殊的組(group(0)),它總是代表整個表示式。該組不包括在 groupCount 的返回值中。
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class RegexMatches
{
public static void main( String args[] ){
// 按指定模式在字串查詢
String line = "This order was placed for QT3000! OK?";
String pattern = "(\D*)(\d+)(.*)";
// 建立 Pattern 物件
Pattern r = Pattern.compile(pattern);
// 現在建立 matcher 物件
Matcher m = r.matcher(line);
if (m.find( )) {
System.out.println("Found value: " + m.group(0) );
System.out.println("Found value: " + m.group(1) );
System.out.println("Found value: " + m.group(2) );
System.out.println("Found value: " + m.group(3) );
} else {
System.out.println("NO MATCH");
}
}
}
輸出:
Found value: This order was placed for QT3000! OK?
Found value: This order was placed for QT
Found value: 3000
Found value: ! OK?
4. C#操作正規表示式
使用的名稱空間 using System.Text.RegularExpressions;
C#中主要使用Regex
類來操作正規表示式,其常用的方法如下:
public bool IsMatch( string input ) | 指示 Regex 建構函式中指定的正規表示式是否在指定的輸入字串中找到匹配項 |
---|---|
public bool IsMatch( string input, int startat ) | 指示 Regex 建構函式中指定的正規表示式是否在指定的輸入字串中找到匹配項,從字串中指定的開始位置開始 |
public static bool IsMatch( string input, string pattern ) | 指示指定的正規表示式是否在指定的輸入字串中找到匹配項 |
public MatchCollection Matches( string input ) | 在指定的輸入字串中搜尋正規表示式的所有匹配項 |
<div>public string Replace( string input, string replacement ) </div>
| 在指定的輸入字串中,把所有匹配正規表示式模式的所有匹配的字串替換為指定的替換字串 |
| public string[] Split( string input ) | 把輸入字串分割為子字串陣列,根據在 Regex 建構函式中指定的正規表示式模式定義的位置進行分割 |
例項一:下面的例項匹配了以 `S` 開頭的單詞:
using System;
using System.Text.RegularExpressions;
namespace RegExApplication
{
class Program
{
private static void showMatch(string text, string expr)
{
Console.WriteLine("The Expression: " + expr);
MatchCollection mc = Regex.Matches(text, expr);
foreach (Match m in mc)
{
Console.WriteLine(m);
}
}
static void Main(string[] args)
{
string str = "A Thousand Splendid Suns";
Console.WriteLine("Matching words that start with `S`: ");
showMatch(str, @"SS*");
Console.ReadKey();
}
}
}
輸出:
Matching words that start with `S`:
The Expression: SS*
Splendid
Suns
例項 2: 下面的例項匹配了以 `m` 開頭以 `e` 結尾的單詞:
using System;
using System.Text.RegularExpressions;
namespace RegExApplication
{
class Program
{
private static void showMatch(string text, string expr)
{
Console.WriteLine("The Expression: " + expr);
MatchCollection mc = Regex.Matches(text, expr);
foreach (Match m in mc)
{
Console.WriteLine(m);
}
}
static void Main(string[] args)
{
string str = "make maze and manage to measure it";
Console.WriteLine("Matching words start with `m` and ends with `e`:");
showMatch(str, @"mS*e");
Console.ReadKey();
}
}
}
輸出:
Matching words start with `m` and ends with `e`:
The Expression: mS*e
make
maze
manage
measure
例項 3:下面的例項替換掉多餘的空格:
using System;
using System.Text.RegularExpressions;
namespace RegExApplication
{
class Program
{
static void Main(string[] args)
{
string input = "Hello World ";
string pattern = "\s+";
string replacement = " ";
Regex rgx = new Regex(pattern);
string result = rgx.Replace(input, replacement);
Console.WriteLine("Original String: {0}", input);
Console.WriteLine("Replacement String: {0}", result);
Console.ReadKey();
}
}
}
輸出:
Original String: Hello World
Replacement String: Hello World
5. C++操作正規表示式
C++裡面使用正規表示式一般有三種:C regex,C ++regex,boost regex
例項一:電子郵件
// Regex.cpp : 定義控制檯應用程式的入口點。
//
#include <regex>
#include <iostream>
#include <stdio.h>
#include <string>
using namespace std;
//電子郵件匹配
bool is_email_valid(const std::string& email)
{
const regex pattern("(\w+)(\.|_)?(\w*)@(\w+)(\.(\w+))+");
/****
const std::regex pattern("(\w+)(\.|_)?(\w*)@(\w+)(\.(\w+))+");
std:: match_results<std::string::const_iterator> result;
bool valid = std::regex_match(email, result,pattern);
//此處result引數可有可無,result是一個字串陣列,用來儲存正規表示式裡面括號的內容。
if(valid&&(result.length()>0))
{
for(int i =0;i<result.length();i++)
{
cout<<result[i]<<endl;
}
}
return valid;
}
例項二:IP
bool is_IPAddress_valid(const std::string& ipaddress)
{
const std::regex pattern("(\d{1,3}).(\d{1,3}).(\d{1,3}).(\d{1,3})");
//三位數的都可以,沒有設定1-255 的條件
std:: match_results<std::string::const_iterator> result;
bool valid = std::regex_match(ipaddress, result, pattern);
if(valid&&(result.length()>0))
{
for(int i =0;i<result.length();i++)
{
cout<<result[i]<<endl;
}
}
return valid;
}
測試:
int main(int argc,char** argv)
{
cout<<"測試4個電子郵件選項"<<endl;
std::string email1 = "marius.bancila@domain.com";
std::string email2 = "mariusbancila@domain.com";
std::string email3 = "marius_b@domain.co.uk";
std::string email4 = "marius@domain";
std::cout << email1 << " : " << (is_email_valid(email1) ? "valid" : "invalid") << std::endl;
std::cout << email2 << " : " << (is_email_valid(email2) ? "valid" : "invalid") << std::endl;
std::cout << email3 << " : " << (is_email_valid(email3) ? "valid" : "invalid") << std::endl;
std::cout << email4 << " : " << (is_email_valid(email4) ? "valid" : "invalid") << std::endl;
cout<<"測試4個IP地址選項"<<endl;
std::string IPAddress1 = "202.20.144.3";
std::string IPAddress2 = "255.02.233.02";
std::string IPAddress3 = "127.256.2.36";
std::string IPAddress4 = "123.-25.56.125";
std::cout << IPAddress1 << " : " << (is_IPAddress_valid(IPAddress1) ? "valid" : "invalid") << std::endl;
std::cout << IPAddress2 << " : " << (is_IPAddress_valid(IPAddress2) ? "valid" : "invalid") << std::endl;
std::cout << IPAddress3 << " : " << (is_IPAddress_valid(IPAddress3) ? "valid" : "invalid") << std::endl;
std::cout << IPAddress4 << " : " << (is_IPAddress_valid(IPAddress4) ? "valid" : "invalid") << std::endl;
return 0 ;
}
6. Javasript操作正規表示式
參考文獻:http://www.runoob.com/js/js-r…
參考文獻:https://www.cnblogs.com/zhuzh…
6.1 JavaScript對正規表示式的支援程度
下面的這些都是JavaScript所不支援的:
匹配字串開始和結尾的A和Z錨。(但我們仍可以使用^和$來匹配字串的開始和結尾)
向後查詢(lookbehind)(注:但是JavaScript完全支援向前查詢(lookahead))
並集和交集類
原子組(atomic grouping)
Unicode支援(單個字元除外,如uFFFF)
命名的捕獲組
s(single,單行)和x(free-spacing,無間隔)匹配模式
條件匹配
正規表示式註釋
6.2 支援正規表示式的RegExp型別
JavaScript是通過RegExp型別來支援正規表示式的。而建立RegExp型別有兩種方法。一種是字面量方法(類似於Perl的語法),另一種是使用JavaScript的RegExp建構函式,下面將逐一介紹。
6.2.1 字面量方法
var expression = /pattern/flags;
其中expression即為正規表示式的名稱,模式(pattern)可以是任何複雜或簡單的正規表示式(但必須是在JavaScript支援範圍內的),標誌(flags)即用來表明正規表示式行為。
下面介紹JavaScript中支援的三個標誌(flags):
- g: 表示全域性(global)模式,表示pattern會應用於所有字串,而不是找到一個匹配項後立即停止。
- i :表示不區分大小寫(ignore)模式。即忽略pattern和字串的大小寫。
- m:表示多行(multiple)模式。 即到一行文字末尾時還會繼續查詢下一行中是否存在匹配的項。
說明:在字面量方法中的flags可以是g、i、m中的任意一個或幾個且這裡的標誌完全適用於之後要講的RegExp建構函式方法。
舉例:
var pattern=/at/gi;
此字面量形式的正規表示式表示在不區分大小寫的情況下在全域性範圍內匹配at。
6.2.2 RegExp建構函式法
var pattern = new RegExp("pattern","flags");
即這種方法使用了RegExp建構函式,並且傳遞了兩個引數(同字面量方法),但值得注意的是:pattern(模式)和flags(標誌)都需要使用引號括起來。
6.2.3 對模式中的元字元轉義的方法
當我們希望使用元字元本身的含義時,我們就需要對元字元進行轉義。比如[ab]c表示ac或bc;若通過轉義,即[ab]c就表示成了[ab]c。但是對於上述兩種不同的建立方法有不同的轉義方式。
首先,請記住在JavaScript中的元字元有 ( [ { ^ $ | ) ? * + . ] ) }。
使用字面量方法建立正規表示式轉義:在需要轉義的正規表示式前加即可。如var pattern = /[ab]c/g;表示在全域性範圍內匹配abc
使用RegExp建構函式建立正規表示式轉義:在需要轉義的正規表示式前加。如var pattern = RegExp(“[ab]c”,”g”);同樣表示在全域性範圍內匹配abc
舉例:
如果希望知道字串XxxxoOoooommmm中o的數量(不區分大小寫),這時就可以使用match方法傳入字串,如:
var string = "XxxxoOoooommmm"; console.log(string.match(/o/ig).length);
輸出為6,這種方法還是很容易的。
6.3 RegExp的例項屬性
無論是何種方法建立的正規表示式,他們都具有下面幾種屬性來描述有關模式的資訊:
- global—表示flags(標誌)中是否設定了g標誌。
- ignoreCase—表示flags(標誌)中是否設定了i標誌。
- lastIndex—表示開始搜尋下一個匹配項的字元位置的整數,從0算起。
- multiple—表示flags(標誌)中是否設定了m標誌。
- source—按照字面量形式返回正規表示式的字串表示。
舉例如下所示:
// var pattern = RegExp("\[ba\]at","gi");//使用RegExp建構函式建立得到的效果和下面使用的字面量方法建立得到的效果相同
var pattern = /[ba]at/gi;
console.log(pattern.global); //true
console.log(pattern.ignoreCase); //true
console.log(pattern.multiline); //ture
console.log(pattern.lastIndex); //0
console.log(pattern.source); // [ba]at
當然,上面程式碼中使用了大量的console.log()顯得很複雜,也可以將這5個屬性作為5個引數直接傳入到console.log()中。如下所示:
var pattern = /[ba]at/gi;
console.log(pattern.global,pattern.ignoreCase,pattern.multiline,pattern.lastIndex,pattern.source); //true true false 0 "[ba]at"
我們還可以將這5個屬性儲存在一個陣列中,再通過console.log()直接輸出陣列,如下所示:
var pattern = /[ba]at/gi;
var properties=[pattern.global,pattern.ignoreCase,pattern.multiline,pattern.lastIndex,pattern.source];
console.log(properties);
6.4 RegExp的例項方法
RegExp的例項主要有兩個方法exec()和test(),並且還有從Object繼承的toString()和toLocaleString()方法,下面將會逐一介紹。
6.4.1 RegExp例項的exec()方法
這個方法接收一個引數,即要應用模式的字串,用於捕獲組。
如果匹配,則返回一個陣列;否則返回null。
且其中返回的陣列還有額外的兩個方法:index和input。index表示匹配項在字串中的位置,input表示應用正規表示式的字串。
舉例如下所示:
var text="mom and dad and baby";
var pattern=/mom( and dad( and baby)?)?/gi;
var matches=pattern.exec(text);
console.log(matches);
如果匹配不了,則matches為null;如果匹配,將會在控制檯中輸出一個陣列
6.4.2 RegExp例項的test()方法
這個方法同樣也接收一個字串,如果pattern(模式)和字串匹配,則返回true,否則返回false。
並且test()方法經常被用在if語句中,舉例如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Regular Expression</title>
</head>
<body>
<input type="text" id="phoneNumber">
<button id="submit">提交</button>
<script>
window.onload=function(){
var btn=document.getElementById("submit");
btn.onclick=function(){
var phoneNumber=document.getElementById("phoneNumber").value;
var pattern=/1[358]d{9}/gi;
if(pattern.test(phoneNumber)){
alert("Yes! Your phoneNumber is legal");
}else{
alert("No!Your phoneNumber is illegal");
}
}
}
</script>
</body>
</html>
6.4.3 RegExp例項的toString()和toLocalString()方法
這兩個方法都會返回正規表示式的字面量,與建立正規表示式的方式無關。
舉例如下:
var pattern=/1[358]d{9}/gi;
console.log(pattern.toString());
console.log(pattern.toLocaleString());
6.5 RegExp的建構函式屬性
RegExp建構函式也包含了一些屬性。值得注意的是,這些屬性有兩種方式來訪問—長屬性名和短屬性名。介紹如下:
- input $_ 最近一次要匹配的字串 。(注意:前者是長屬性名,後者是短屬性名,下同)
- lastMatch $& 最近一次的匹配向。
- lastParen $+ 最近一次匹配的捕獲組。
- leftContext $` input字串中lastMatch之前的文字
- RightContext $` input字串中lastMatch之後的文字
- multiline $* 布林值,表示是否所有表示式都使用多行模式
注意:Opera不支援上面的1236對應的四個屬性,IE不支援multiline屬性。
舉例如下所示:
var text="this has been a short summer";
var pattern=/(.)hort/g;
if(pattern.test(text)){
console.log(RegExp.input);//this has been a short summer
console.log(RegExp.leftContext);//this has been a
console.log(RegExp.rightContext);//summer
console.log(RegExp.lastParen);//s
console.log(RegExp.lastMatch);//short
console.log(RegExp.multiline);//undefined
}