一、正則表達(dá)式的用途(搜索和替換)
- 1.1.正則表達(dá)式(
regular expression,簡(jiǎn)稱regex)是一種工具,和其他的工具是一樣的,它是人們?yōu)榱私鉀Q某一類問(wèn)題而發(fā)明的,要想理解正則表達(dá)式及其功用,最好的辦法是了解它們可以解決什么樣的問(wèn)題。 - 1.2. 在編寫(xiě)處理字符串的程序時(shí),經(jīng)常會(huì)有查找符合某些復(fù)雜規(guī)則的字符串或者替換一些字符串。正則表達(dá)式就是用于描述這些規(guī)則的工具。換句話說(shuō),正則表達(dá)式就是記錄文本規(guī)則的代碼
- 1.3.正則表達(dá)式是對(duì)字符串操作的一種邏輯公式,用事先定義好的一些特定字符、及這些特定字符的組合,組成一個(gè)"規(guī)則字符串",這個(gè)"規(guī)則字符串"用來(lái)表達(dá)對(duì)字符串的一種過(guò)濾邏輯。
- 1.4.-幾乎所有的程序設(shè)計(jì)語(yǔ)言都支持正則表達(dá)式,例如:
OC,java,c#,python,js等 - 1.5.在很多文本編輯器里,可以使用正則表達(dá)式進(jìn)行檢索,正則表達(dá)式是文本處理方面功能最強(qiáng)大的工具之一,正則表達(dá)式語(yǔ)言來(lái)構(gòu)造正則表達(dá)式(最終構(gòu)造出來(lái)的字符串就稱為正則表達(dá)式),正則表達(dá)式用來(lái)完成搜索和替換的操作,當(dāng)然,Xcode同樣支持正則表達(dá)式!
二、匹配單個(gè)字符(下面的都將調(diào)用textRegex()方法)
-
2.1.匹配純文本(
"ben")
匹配純文本import UIKit class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() // 匹配單個(gè)字符 view.addSubview(label) let str = "Hello, my name is Ben. Please visit my ben website at https://www.forta.com/." label.attributedText = textRegex(pattern: ".a.",str: str, font: 22) } // 1.匹配純文本 func textRegex(pattern: String,str: String,font: CGFloat) -> NSMutableAttributedString{ //富文本設(shè)置 let attributeString = NSMutableAttributedString(string:str) do { // 1.1.定義規(guī)則 //let pattern = "ben" // 1.2.創(chuàng)建正則表達(dá)式對(duì)象 let regex = try NSRegularExpression(pattern: pattern, options: NSRegularExpression.Options.caseInsensitive) // 1.3.開(kāi)始匹配 let res = regex.matches(in: str, options: NSRegularExpression.MatchingOptions(rawValue: 0), range: NSMakeRange(0, str.count)) for checkingRes in res { print("range\(checkingRes.range)") // substring 截取符合規(guī)定規(guī)則的字符串 print((str as NSString).substring(with: checkingRes.range)) //從文本checkingRes.range個(gè)字符字體HelveticaNeue-Bold attributeString.addAttribute(NSAttributedStringKey.font, value: UIFont(name: "HelveticaNeue-Bold", size: 22)!,range: checkingRes.range) //設(shè)置字體顏色 attributeString.addAttribute(NSAttributedStringKey.foregroundColor, value: UIColor.blue,range: checkingRes.range) //設(shè)置文字背景顏色 attributeString.addAttribute(NSAttributedStringKey.backgroundColor, value: UIColor.green,range: checkingRes.range) } return attributeString } catch { print(error) } return attributeString } lazy var label: UILabel = { let label1: UILabel = UILabel(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: UIScreen.main.bounds.size.height)) label1.font = UIFont.systemFont(ofSize: 22) label1.numberOfLines = 0 label1.backgroundColor = UIColor.white return label1 }() } -
2.2.匹配任意字符(注意:下面的兩句代碼調(diào)了textRegex方法)
前面見(jiàn)到的正則表達(dá)式都是一些靜態(tài)的純文本,它們根本體現(xiàn)不出來(lái)正則表達(dá)式的威力,下面,我們一起來(lái)看看如何用正則表達(dá)式去匹配不可預(yù)知的字符。在正則表達(dá)式里,特殊字符(或字符集合)用來(lái)給出要搜索的東西。"."字符(英文句號(hào))可以匹配任何一個(gè)單個(gè)的字符。
let str = "Hello, my name is Ben. Please visit my ben website at https://www.forta.com/." label.attributedText = textRegex(pattern: ".a.",str: str, font: 22) -
2.3. 用正則表達(dá)式w.t進(jìn)行的搜索將匹配到wht和wat(還能匹配到一些毫無(wú)意義的單詞)
w.tlet str = "HellomynameisBen.whtareyouwatoulikeme" label.attributedText = textRegex(pattern: "w.t",str: str, font: 22) -
2.4. “.”字符可以匹配任何單個(gè)的字符,字母,數(shù)字甚至只“.”字符本身
let str = "HellomynameisBen.whtareyouwatoulikeme" label.attributedText = textRegex(pattern: "n.",str: str, font: 22) -
2.5.匹配特殊字符
“.”字符在正則表達(dá)式里面有著特殊的含義,如果模式里需要一個(gè)“.”,就要想辦法告訴正則表達(dá)式你需要的是“.”字符本身而不是它在正則表達(dá)式里的特殊含義。為此,你必須在“.”前面加一個(gè)(反斜杠)字符來(lái)對(duì)它進(jìn)行轉(zhuǎn)義。\是一個(gè)元字符(metacharacter,表示“這個(gè)字符有特殊的含義”)。
-
在正則表達(dá)式里面,\字符永遠(yuǎn)出現(xiàn)在一個(gè)有著特殊含義的字符串序列的開(kāi)頭,這個(gè)序列可以由一個(gè)或者多個(gè)字符構(gòu)成。下面看到的是
\.序列,在后面的章節(jié)里面還會(huì)看到更多使用了\字符的例子。
let str = "Hellomynamei.sBen.whtarbyouwatoulikea.se" label.attributedText = textRegex(pattern: ".e.\\.s",str: str, font: 22) 注意:如果需要搜索\本身,就必須對(duì)\字符進(jìn)行轉(zhuǎn)義;相應(yīng)的轉(zhuǎn)義序列是兩個(gè)連續(xù)的反斜杠字符
\\。
三、匹配一組字符(下面會(huì)涉及字符集合)
3.1.說(shuō)明字符集合則能匹配特定的字符和字符區(qū)間。
-
3.2.匹配多個(gè)字符中的某一個(gè)
let str = "Hellomynamei.sBen.whtareb.syouwatoulikea.se" label.attributedText = textRegex(pattern: "[mk]e.\\.s",str: str, font: 22)解釋:
"[mk]e.\\.s"是e的前面只能是 字母m或者k -
3.2.利用字符集合區(qū)間
A-Z: 匹配從A到Zdenka所有大寫(xiě)字母
a-z: 匹配a-z的所有小寫(xiě)的字母
A-F: 匹配從A到F所有大寫(xiě)字母
A-z: 匹配ASCII字符A到ASCII字符z的所有字母。這個(gè)模式一般不常用,因?yàn)樗€包含著[^等在ASCII字符表里面排列在z和a之間的字符。字符區(qū)間的首、尾字符可以是ASCII字符表里的任意字符。但在實(shí)際工作中,最長(zhǎng)喲個(gè)的字符區(qū)間還是數(shù)字字符區(qū)間和字母字符區(qū)間。提示:在定義一個(gè)字符區(qū)間一定要避免這個(gè)區(qū)間的尾字符小于它的首字符(例如:[3-1])。這種區(qū)間是沒(méi)有意義的,二往往會(huì)讓整個(gè)模式失效。
-(連字符):是一個(gè)特殊的元字符,作為元字符它只能用在[和]之間。在字符集合意外的地方,“-”只是一個(gè)普通的字符,只能與“-”本身相匹配。因此,在正則表達(dá)式里面,“-”字符不需要被轉(zhuǎn)義。
利用字符集合區(qū)間let str = "<BODY BGCOLOR=#336633 TEXT=#FFFFFF MARGINWIDTH=0 MARGINHEIGHT=0 TOPMARGIN=0 LEFTMARGIN=0>" label.attributedText = textRegex(pattern: "#[0-9A-Fa-f][0-9A-Fa-f][0-9A-Fa-f][0-9A-Fa-f][0-9A-Fa-f][0-9A-Fa-f]",str: str, font: 22)- 分析:這里使用的模式以普通字符
#開(kāi)頭,隨后是6個(gè)同樣的[0-9A-Fa-f]字符集合。這將匹配一個(gè)由字符#開(kāi)頭,然后6個(gè)數(shù)字或字母A-F(大小寫(xiě)均可)的字符串
- 分析:這里使用的模式以普通字符
-
3.3.取非匹配
字符集合通常用來(lái)指定一組必須匹配其中之一的字符。但在某些場(chǎng)合,我們需要反過(guò)來(lái)做給出一組不需要得到的字符,換句話說(shuō),除了那個(gè)字符集合的字符,其他的字符都可以匹配。我們可以用元字符
^
來(lái)表明你想對(duì)一個(gè)字符集合進(jìn)行取非匹配。這與邏輯運(yùn)算很相似,只是這里的操作數(shù)是字符集合而已。
取非匹配let str = "Real Love is n2 just instin1t, but intent." label.attributedText = textRegex(pattern: "[no][^a-zA-Z]",str: str, font: 22)- 解釋:
[no]意思是第一個(gè)取n或者o都可以,[^a-zA-Z]意思是除了小寫(xiě)a~z和大寫(xiě)A~Z的都不可以取,^是非的意思
^的效果將作用于給定字符集合里的所有字符或字符區(qū)間,而不是僅限于緊跟在^字符后面的那一個(gè)字符或者字符區(qū)間。
- 解釋:
3.4.總結(jié)
元字符[和]用來(lái)定義一個(gè)字符集合,其含義是必須匹配該集合里的字符之一。定義一個(gè)字符集合的具體的做法有兩種:1、把所有的字符都列舉出來(lái);2、是利用元字符-以字符區(qū)間的方式給出。字符集合可以用元字符^來(lái)求非;這將把給定的字符集合強(qiáng)行排除在匹配操作以外,除了該字符集合里的字符,其他字符都可以進(jìn)行匹配。
四、使用元字符(利用元字符去匹配特定的字符或字符類型)
-
4.1.對(duì)特定的字符進(jìn)行轉(zhuǎn)義
元字符是一些在正則表達(dá)式里有著特殊含義的字符。英文句號(hào)
.是一個(gè)元字符,他可以用來(lái)匹配任意一個(gè)單個(gè)字符,類似地,在方括號(hào)[也是一個(gè)元字符,它標(biāo)志著一個(gè)字符集合的開(kāi)始。
元字符是無(wú)法用來(lái)替代它們本身,因?yàn)樵谡齽t表達(dá)式里面有著特殊的含義,比如,你不能用一個(gè)[來(lái)匹配[本身,也不能使用.來(lái)匹配.本身,看下面的例子
let str = "var myArray = new Array() if (myArray[0] = 0)" label.attributedText = textRegex(pattern: "myArray[0]",str: str, font: 22)說(shuō)明:為什么沒(méi)有匹配到
myArray[0]呢?因?yàn)椋篬和]在正則表達(dá)式里是用來(lái)定義一個(gè)字符集合(而不是[和]本身)的元字符,所以,myArray[0]將匹配myArray后面跟著一個(gè)該集合成員的情況,而那個(gè)集合只有一個(gè)成員0.因此,myArray[0]只能匹配到myArray0。 -
4.2. 如何才能匹配到myArray[0]呢???
答案是對(duì)元字符進(jìn)行轉(zhuǎn)義 前面加
\\反斜杠,這樣就可以匹配本身了,[和]就不再是元字符。
反斜杠let str = "var myArray = new Array() if (myArray[0] = 0)" label.attributedText = textRegex(pattern: "myArray\\[0]",str: str, font: 22)如果想匹配到0-9之間的數(shù)字都可以匹配的話,就需要對(duì)集合進(jìn)行匹配了
let str = "var myArray[8] = new Array() if (myArray[0] = 0)" label.attributedText = textRegex(pattern: "myArray\\[[0-9]]",str: str, font: 22)
任何一個(gè)元字符都可以通過(guò)給它加上一個(gè)反斜杠字符 \作為前綴的辦法來(lái)轉(zhuǎn)義,對(duì)元字符進(jìn)行轉(zhuǎn)義需要用到\字符也是一個(gè)元字符,它的特殊含義是對(duì)其他的額字符進(jìn)行轉(zhuǎn)義,在需要匹配本身的時(shí)候,我們必須把它轉(zhuǎn)移為\\

let str: String = "\\Users\\wangchong\\Desktop\\"
label.attributedText = textRegex(pattern: "\\\\",str: str, font: 22)
-
4.2.匹配空白字符
元字符大多分為2種,一種是用來(lái)匹配文本的(比如
.),另一種是正則表達(dá)式的語(yǔ)法所要求的(比如[和])。隨著學(xué)習(xí)的深入,我們會(huì)發(fā)現(xiàn)越來(lái)越多的這兩種語(yǔ)法,下面是匹配空白字符的元字符。
特殊元字符
let str: String = "Oviri is an \n\n 1894 ceramic sculpture by the French artist Paul Gauguin." label.attributedText = textRegex(pattern: "\n\n",str: str, font: 22)\n\n作為文本結(jié)束的標(biāo)簽- 元字符我們已經(jīng)見(jiàn)了好幾個(gè)了,但是差異性我們真的鏈接嗎?比如
.和[是元字符(前提是沒(méi)有對(duì)他們進(jìn)行轉(zhuǎn)義);f、n、r、t、也是元字符(前提是對(duì)它們進(jìn)行了轉(zhuǎn)義),否則它們將被視為普通的字符,從而也只能匹配它們本身。
- 元字符我們已經(jīng)見(jiàn)了好幾個(gè)了,但是差異性我們真的鏈接嗎?比如
-
4.3.匹配特定的字符類別
.匹配任意字符[和]多個(gè)字符中的某一個(gè)^取非匹配字符集合(匹配多個(gè)字符中的某一個(gè))是最常見(jiàn)的匹配形式,而一些常用的字符集合可以用特殊的元字符來(lái)代替。這些元字符匹配的是某一類別的字符(術(shù)語(yǔ)為字符類)??聪旅娴睦?/p>
-
4.3.1. 匹配數(shù)字(與非數(shù)字)
數(shù)字元字符
let str: String = "Oviri is an 1894 ceramic scu1lpture by the French artist Paul Gauguin." label.attributedText = textRegex(pattern: "\\d",str: str, font: 22) 提示:正則表達(dá)式的語(yǔ)法是區(qū)分字母大小寫(xiě)的。
\d匹配數(shù)字,\D匹配非數(shù)字,它們正好相反。其他的元字符也一樣-
4.3.2.匹配字母和數(shù)字(與非字母和數(shù)字)
字母數(shù)字元字符 -
例如
let str: String = "你%¥嗎()==12_3" label.attributedText = textRegex(pattern: "\\W",str: str, font: 22) -
4.3.3.匹配空字符串(與空白字符)
看下面的例子
匹配空字符串let str: String = "11213 A1C2E3 48075 48237 M14F2 90046 H1H2H2" label.attributedText = textRegex(pattern: "\\s",str: str, font: 22)提示:用來(lái)匹配退格字符的
[\b]元字符就是一個(gè)特例;它不在類元字符\s的覆蓋范圍內(nèi),當(dāng)然也就沒(méi)有被排除在類元字符\S的覆蓋范圍外。
-
4.4.使用POSIX字符類
let str: String = "K$P1-21_3@" label.attributedText = textRegex(pattern: "[:alnum:]",str: str, font: 22)
五、重復(fù)匹配
-
5.1.匹配一個(gè)或者多個(gè)字符(
+)-
+號(hào)匹配一個(gè)或多個(gè)字符(至少一個(gè);不匹配0個(gè)字符的情況),比如c匹配c本身,c+將匹配一個(gè)或多個(gè)連續(xù)出現(xiàn)的c。類似地,[0-9]匹配任意單個(gè)數(shù)字,[0-9]+將匹配一個(gè)或多個(gè)連續(xù)的數(shù)字。
let str: String = "The world for.text@text.text is a fine place, and worth fighting The world is a finefor.hext@tdxt.text place, and worth fighting for." label.attributedText = textRegex(pattern: "\\w+@\\w+\\.\\w+",str: str, font: 22)-
如何把上面的
for也匹配上
let str: String = "The world for.text@text.text is a fine place, and worth fighting The world is a finefor hext@tdxt.text place, and worth fighting for." label.attributedText = textRegex(pattern: "[\\w.]+@\\w+\\.\\w+",str: str, font: 22)
說(shuō)明:上面沒(méi)有對(duì)字符集合
[\w.]里的.字符進(jìn)行轉(zhuǎn)義。盡管如此,它還是把原始文本里的.字符匹配出來(lái)了。一般來(lái)說(shuō),當(dāng)在字符集合里使用的時(shí)候,像.和+這樣的元字符將被解釋為普通的字符,不需要被轉(zhuǎn)義,但轉(zhuǎn)義了也沒(méi)有壞處。[\w.]的使用效果與[\w.\.]是一樣的 -
-
-
5.2.匹配零個(gè)或多個(gè)字符
匹配零個(gè)或多個(gè)字符let str: String = "The world .text@text.com is a fine place, and worth fighting The world is a finefor hext@tdxt.text place, and worth fighting for." label.attributedText = textRegex(pattern: "\\w+[\\w.]*@[\\w.]+\\.\\w+",str: str, font: 22)*與+的區(qū)別是:+匹配一個(gè)或者多個(gè)字符(或字符集合),最少也要匹配一次;*匹配零個(gè)或任意多個(gè)字符(或字符集合),可以沒(méi)有匹配。
*是一個(gè)元字符。如果需要匹配*本身,就必須對(duì)它進(jìn)行轉(zhuǎn)義。 -
5.3.匹配零個(gè)或者一個(gè)字符(
?)
?只能匹配一個(gè)字符(或字符集合)的零次或一次出現(xiàn),最多不超過(guò)一次,如果需要在一段文本里匹配某個(gè)特定的字符(或字符集合)而該字符可能出現(xiàn),也可能不出現(xiàn),?無(wú)疑是最佳的選擇。
let str: String = "The URL is http://www.forta.com/, to connect securely use https://www.forta.com/ instand." label.attributedText = textRegex(pattern: "https?://[\\w.]+",str: str, font: 22)同樣
?也是一個(gè)元字符,匹配本身的話也需要進(jìn)行轉(zhuǎn)義。 -
5.4.匹配的重復(fù)的次數(shù)
-
5.4.1、為重復(fù)匹配次數(shù)設(shè)定一個(gè)精確的值
let str: String = "<BODY BGCOLOR=#336633> TEXT=#FFFFFF MARGINWIDTH=0 MARGINHEIGHT=0 TOPMARGIN=0" label.attributedText = textRegex(pattern: "[0-9A-Fa-f]{6}",str: str, font: 22){6}:意味著要連續(xù)匹配6次[0-9A-Fa-f]區(qū)間的值 -
5.4.2、為重復(fù)匹配次數(shù)設(shè)定一個(gè)區(qū)間
{}:語(yǔ)法不僅僅可以設(shè)置匹配的次數(shù),還可以設(shè)置匹配的最小和最大次數(shù)
如: {1,3}代表連續(xù)匹配1~3次之間,當(dāng)然之前的?其實(shí)就是等價(jià)于?={0,1} -
5.4.3、匹配“至少重復(fù)多少次”
{}語(yǔ)法還可以設(shè)置至少重復(fù)的次數(shù),也就是不用設(shè)置最大重復(fù)的次數(shù),比如{2,}
匹配“至少重復(fù)多少次”let str: String = "1001: $496.80 1002: $1290.69 1003: $26.43 1004: $613.42 1007" label.attributedText = textRegex(pattern: "\\d+: \\$\\d{3,}\\.\\d{2}",str: str, font: 22)注意:
{3,}中的逗號(hào)千萬(wàn)別漏掉,否則就變成了精準(zhǔn)匹配3位了。
-
-
5.5.防止過(guò)度匹配
?只能匹配0個(gè)或者一個(gè)字符,{n}和{m,n}也有一個(gè)重復(fù)次數(shù)的上限,之前的例子都沒(méi)有上限,下面舉一個(gè)例子來(lái)說(shuō)明
貪婪型和懶惰型說(shuō)明:貪婪型為什么會(huì)匹配and,那是因?yàn)樨澙沸驮址谶M(jìn)行匹配的時(shí)候是多多益善而不是適可而止。它們會(huì)盡可能地從一段文本的開(kāi)頭一直匹配到這段文本的末尾,而不是從這段文本的開(kāi)頭匹配到第一個(gè)匹配為止。
- 解決辦法是:在貪婪型元字符的后面加上
? -
下面是常用的貪婪型元字符和他們的懶惰型版本
- 解決辦法是:在貪婪型元字符的后面加上
5.6.總結(jié)
正則表達(dá)式的真正威力體現(xiàn)在重復(fù)次數(shù)匹配方面。上面介紹了+(匹配字符或字符集合的一次或多次重復(fù)出現(xiàn)),*(匹配字符或字符集合的0次或多次重復(fù)出現(xiàn)),?(匹配字符或字符集合的0次或一次出現(xiàn))等幾個(gè)元字符的用法。要想獲得更精準(zhǔn)的控制,你可以使用{}語(yǔ)法來(lái)精確地設(shè)定一個(gè)重復(fù)次數(shù)或是重復(fù)次數(shù)的最小值和最大值。元字符分“貪婪型”和“懶惰型”兩種,使用時(shí)要防止過(guò)度匹配時(shí)候可以使用懶惰型元字符來(lái)創(chuàng)造適合自己的表達(dá)式。
六、位置匹配
-
6.1.邊界
下面的例子只是想配
cat這個(gè)單詞,但是scattered也被匹配到了,這不是我們想要的結(jié)果,后面再解決。
邊界let str: String = "The cat scattered his food all over the room." label.attributedText = textRegex(pattern: "cat",str: str, font: 22) -
6.2.單詞邊界
\b可以用來(lái)限制單詞的邊界,也就是規(guī)定單詞的開(kāi)頭和結(jié)尾。,如下所示\b單詞邊界let str: String = "The cat scattered his food all over the room." label.attributedText = textRegex(pattern: "\\bcat\\b",str: str, font: 22)說(shuō)明:
\b:匹配的是這樣一個(gè)位置,這個(gè)位置位于一個(gè)能夠用來(lái)構(gòu)成單詞的字符(字母,數(shù)字,下劃線,也就是與\w相匹配的字符)和一個(gè)不能用來(lái)構(gòu)成單詞的字符(也就是與\w相匹配的字符)之間。
注意:要想精準(zhǔn)的匹配某一個(gè)單詞必須在其前后都要加上\b單詞\b
-
如果不想匹配一個(gè)單詞的邊界,那么就可以使用
\B了,看下面的例子
let str: String = "Please enter the nine-digit id as it appears on your color - coded pass-key." label.attributedText = textRegex(pattern: "\\B-\\B",str: str, font: 22)\\B-\\B: 將匹配一個(gè)前后都不是單詞邊界的連字符。nine-digit和pass-key不能與之匹配,但color - coded中的連字符可以與之匹配。
匹配單詞的還有\\<單詞\\>,但是swift4.0不支持,本人已經(jīng)驗(yàn)證過(guò)了。 -
6.3、字符的邊界
單詞邊界可以用來(lái)進(jìn)行與單詞有關(guān)位置的匹配(單詞的開(kāi)頭,單詞的結(jié)束,整個(gè)單詞等)。字符串邊界有著類似的用途,只不過(guò)是用來(lái)進(jìn)行與字符串有關(guān)的位置匹配而已(字符串的開(kāi)頭,字符串的結(jié)束,整個(gè)字符串等)。用來(lái)定義字符串邊界的元字符有兩個(gè):一個(gè)是用來(lái)定義字符串開(kāi)頭的
^,另一個(gè)是用來(lái)定義字符串結(jié)尾的$.
- 總結(jié):正則表達(dá)式不僅僅可以用來(lái)匹配任意長(zhǎng)度的文本塊,還可以用來(lái)匹配出現(xiàn)在字符串中特定位置的文本。
\b用來(lái)指定一個(gè)單詞的邊界(\B剛好相反)。^和$用來(lái)指定字符串的邊界(字符串的開(kāi)頭和字符串的結(jié)束)。如果與(?m)配合使用,^和$還將匹配在一個(gè)換行處開(kāi)頭或結(jié)束的字符串(此時(shí),換行符將被視為一個(gè)字符串分隔符)。
七、使用字表達(dá)式(元字符和字符是正則表達(dá)式的基本構(gòu)件)
-
7.1、什么是子表達(dá)式?
let str: String = "Hello, my name is Ben Forta, and I am the author of books on SQL, ColdFusion, WAP, Windows 2000, and other subjects." label.attributedText = textRegex(pattern: " {2,}",str: str, font: 22) :是HTML語(yǔ)言中的非換行空格字符。在這里使用模式 {2,}的本意是希望它能把?連續(xù)兩次或更多次的重復(fù)出現(xiàn)找出來(lái),但它沒(méi)能給出我們所預(yù)期的結(jié)果。為什么會(huì)這樣?因?yàn)?strong>{2,}只作用于緊挨著它的前一個(gè)字符,那是一個(gè)分號(hào)。如此一來(lái),這個(gè)模式只能匹配像 ;;;這樣的文本,但無(wú)法匹配  。 -
7.2、子表達(dá)式
字表達(dá)式:是一個(gè)更大的表達(dá)式的一部分;把一個(gè)表達(dá)式劃分為一系列表達(dá)式的目的是為了把那些字表達(dá)式當(dāng)做一個(gè)獨(dú)立元素來(lái)使用。字表達(dá)式必須用
()括起來(lái)。()是元字符。如果要匹配()的話需要進(jìn)行對(duì)它轉(zhuǎn)義??聪旅娴睦?br>()的使用let str: String = "Hello, my name is Ben Forta, and I am the author of books on SQL, ColdFusion, WAP, Windows 2000, and other subjects." label.attributedText = textRegex(pattern: "( ){2,}",str: str, font: 22)解釋:
( )是一個(gè)字表達(dá)式,它將被視為一個(gè)獨(dú)立的元素,而緊跟著在它后面的{2,}將做用于這個(gè)字表達(dá)式而不是僅僅作用于;。
"(\d{1,3}\.){3}\d{1,3}"let str: String = "Pinging hog.forta.com [12.159.46.200] with 32 bytes of data:" label.attributedText = textRegex(pattern: "(\\d{1,3}\\.){3}\\d{1,3}",str: str, font: 22)上面的例子中
(\\d{1,3}\\.)是一個(gè)子表達(dá)式,上面的匹配規(guī)則還可以寫(xiě)為"(\\d{1,3}\\.?){4}"和"(\\d{1,3}\\.){3}(\\d{1,3})"。-
下面再寫(xiě)一個(gè)子表達(dá)式的匹配
子表達(dá)式的匹配let str: String = "Hope clouds 1987-09-02 observation." label.attributedText = textRegex(pattern: "(19|20)\\d{2}",str: str, font: 22)
解釋:
|是或的意思。 -
-
7.3、子表達(dá)式的嵌套(下面的例子沒(méi)有正確匹配:待解決)
子表達(dá)式是允許嵌套的,實(shí)際上,子表達(dá)式允許多重嵌套,這種嵌套的層次在理論上沒(méi)有限制,但在實(shí)際上應(yīng)該合理的嵌套。下面的例子將全面的展示
子表達(dá)式的嵌套let str: String = "Pinging hog.forta.com [12.159.46.200] with 32 bytes of data:" label.attributedText = textRegex(pattern: "(((\\d{1,2})|(1\\d{2})|(2[0-4]\\d)|(25[0-5]))\\.){3}(((25[0-5])|(2[0-4]\\d)|(1\\d{2})|\\d{1,2}))" ,str: str, font: 22)注意:最后一個(gè)匹配的時(shí)候三位數(shù)要放到前面,否則的話匹配到兩位數(shù),
200的最后一個(gè)0就不能匹配上了 7.4、總結(jié)
子表達(dá)式的作用是把同一個(gè)表達(dá)式的各個(gè)相關(guān)部分組合在一起。子表達(dá)式必須用()來(lái)定義。子表達(dá)式的常見(jiàn)用途包括: 對(duì)重復(fù)次數(shù)元字符的作用對(duì)象作出精確的設(shè)定和控制、對(duì)|操作符條件作出準(zhǔn)確額定義等,如有必要,子表達(dá)式還允許嵌套使用。
八、回溯引用,前后一致匹配
-
8.1、回溯引用的作用(看下面的例子)
let str: String = "<BODY><H1>Welcom to my Homepage</H1>\nContent is divided into two sections:<BR>\n <H2>ColodFusion</H2>\nInformation about Macromedia ColodFusion.\n <H2>Wrieless</H2>\n Information about Buletooth, 802.11, and more.\n <H2>This is not valid HTML</H3>\n</BODY>" label.attributedText = textRegex(pattern: "<[Hh][1-6]>.*?</[Hh][1-6]>" ,str: str, font: 22)解釋:上面匹配按照規(guī)則是正確的,但是按照語(yǔ)法最后一個(gè)匹配是不正確的,因?yàn)镠2和H3是不對(duì)應(yīng)的標(biāo)簽。為了解決這個(gè)問(wèn)題,下面闡述:回溯引用
-
8.2、回溯引用匹配
-
8.2.1、尋找連著的兩個(gè)相同單詞
尋找連著的兩個(gè)相同單詞let str: String = "This is a block of of text,serveral words here are repeated,and and they should not not be." label.attributedText = textRegex(pattern: "[ ]+(\\w+)[ ]+\\1" ,str: str, font: 22)解釋:
[ ]+匹配一個(gè)或多個(gè)空格,\w+匹配一個(gè)或多個(gè)字母數(shù)字字符,[ ]+匹配隨后的空格,注意\w+是括在括號(hào)里的,它是一個(gè)子表達(dá)式。這個(gè)子表達(dá)式不是用來(lái)進(jìn)行重復(fù)匹配的,這里不涉及到重復(fù)匹配的問(wèn)題。這個(gè)子表達(dá)式只是把整個(gè)模式的一部分單獨(dú)劃分出來(lái)以便在后面引用。這個(gè)模式的最后一部分是\1;這是一個(gè)回溯引用。而它引用的正是前面劃分出來(lái)的那個(gè)子表達(dá)式;當(dāng)(\w+)匹配到單子of的時(shí)候,\1也匹配單詞of;當(dāng)(\w+)匹配到單詞and的時(shí)候,\1也匹配到單詞and。
回溯引用指的是模式的后半部分引用在前半部分中定義的子表達(dá)式。
\1代表模式里的第一個(gè)子表達(dá)式,\2代表模式里的第2個(gè)子表達(dá)式,以此類推,上面的例子將匹配到同一個(gè)單詞的連續(xù)兩次重復(fù)出現(xiàn)。 -
8.2.2、解決8.1的最后一個(gè)不正確標(biāo)簽的匹配
let str: String = "<BODY><H1>Welcom to my Homepage</H1>\nContent is divided into two sections:<BR>\n <H2>ColodFusion</H2>\nInformation about Macromedia ColodFusion.\n <H2>Wrieless</H2>\n Information about Buletooth, 802.11, and more.\n <H2>This is not valid HTML</H3>\n</BODY>" label.attributedText = textRegex(pattern: "<[Hh]([1-6])>.*?</[Hh]\\1>" ,str: str, font: 22)
解釋:
([1-6])是一個(gè)集合的子表達(dá)式,\1匹配前面匹配到的([1-6]),所以說(shuō)H2只能匹配到H2
注意:不同的正則表達(dá)式在實(shí)現(xiàn)回溯引用的語(yǔ)法方面往往有著巨大的差異。
提示:回溯引用只能用來(lái)引用模式里的子表達(dá)式((用(和))括起來(lái)的正則表達(dá)式片段)。回溯引用通常從1開(kāi)始計(jì)數(shù)(\1、\2等)。在許多實(shí)現(xiàn)里,第0個(gè)匹配(\0)可以用來(lái)代表整個(gè)正則表達(dá)式。其實(shí)子表達(dá)式是通過(guò)它們的相對(duì)位置來(lái)引用的:\1對(duì)應(yīng)著第1個(gè)子表達(dá)式,\5對(duì)應(yīng)著第5個(gè)子表達(dá)式等等。這種語(yǔ)法是有問(wèn)題的:如果子表達(dá)式的相對(duì)位置發(fā)生了變化,整個(gè)模式也許就不能再完成原來(lái)的工作,刪除或者添加子表達(dá)式的后果可能更為嚴(yán)重。解決辦法:是運(yùn)用命令捕獲。 -
8.3、回溯引用在替換操作中的應(yīng)用(沒(méi)理解透)
-
8.4.大小寫(xiě)轉(zhuǎn)換
大小寫(xiě)轉(zhuǎn)換
查找
替換使用:$\\U$2\E$3let str: String = "<BODY><H1>Welcom to my Homepage</H1>\nContent is divided into two sections:<BR>\n <H2>ColodFusion</H2>\nInformation about Macromedia ColodFusion." label.attributedText = textRegex(pattern: "(<[Hh]1>)(.*?)(</[Hh]1>)" ,str: str, font: 22)分析:
"(<[Hh]1>)(.*?)(</[Hh]1>)"是三個(gè)子表達(dá)式就是為了使用回溯引用,說(shuō)一下替換部分:$1包含著開(kāi)始標(biāo)簽,U$2\E把第二個(gè)子表達(dá)式(b標(biāo)題文字)轉(zhuǎn)換為大寫(xiě),$3包含著結(jié)束標(biāo)簽。 -
8.5、總結(jié)
子表達(dá)式用來(lái)定義字符或表達(dá)式的集合。除了可以用在重復(fù)匹配操作中意外,子表達(dá)式還可以在模式的內(nèi)部被引用。這種引用被稱為回溯引用?;厮菀玫恼Z(yǔ)法在不同的正則表達(dá)式實(shí)現(xiàn)里有很大的差異?;厮菀迷谖谋酒ヅ浜臀谋咎鎿Q操作里非常有用。
九、前后查找
-
9.1、向前查找
向前查找指定了一個(gè)必須匹配但不在結(jié)果中返回的模式。向前查找實(shí)際就是一個(gè)子表達(dá)式,而且從格式上看也確實(shí)如此。從語(yǔ)法上看,一個(gè)向前查找模式其實(shí)就是一個(gè)以?=開(kāi)頭的子表達(dá)式,需要匹配的文本跟在=后面
在向前查找里,被匹配的文本包含在最終返回的匹配結(jié)果里,被稱為“不消費(fèi)”。反之為消費(fèi)。xiang
注意:向前查找和向后查找匹配本身其實(shí)是有返回結(jié)果的,只是這個(gè)結(jié)果的字節(jié)長(zhǎng)度永遠(yuǎn)是0而已。因此,前后查找操作有時(shí)也被稱為零寬度匹配操作。
其實(shí),任何一個(gè)子表達(dá)式都可以轉(zhuǎn)換為一個(gè)向前查找表達(dá)式,只要給它加上一個(gè)?=前綴即可。在同一個(gè)搜索模式里可以使用多個(gè)向前查找表達(dá)式,它們可以出現(xiàn)在模式里的任意位置(而不僅僅是出現(xiàn)在整個(gè)模式的開(kāi)頭,就像你們?cè)谏厦婵吹降哪菢?。?/p> -
9.2、向后查找
?=被稱為向前查找的操作符,許多正則表達(dá)式還支持向后查找,也就是查找出現(xiàn)在被匹配文本之前的字符(但不消費(fèi)它也就是不包含其后的文本),向后查找操作符是?<=。
?<=與?=使用方法大同小異,它必須在一個(gè)子表達(dá)式里,而且后跟要匹配的文本。
向后查找let str: String = "ABC01: $23.45\nHGG42: $5.31\nCFMX1: $899.00\nXTC99: $69.96\nTotal items founf : 4" label.attributedText = textRegex(pattern: "(?<=\\$)[0-9.]+" ,str: str, font: 22)我們想要的是以
$為基礎(chǔ)匹配后面的消費(fèi)金額,顯然最后一種匹配最好。
提示:向前查找模式長(zhǎng)度是可變的,它們可以包含.和+之類的元字符,所以非常靈活,而向后查找的模式只能是固定長(zhǎng)度,這是一條幾乎所有的正則表達(dá)式實(shí)現(xiàn)都遵循的限制。 -
9.3.把向前查找和向后查找結(jié)合起來(lái)
把向前查找和向后查找結(jié)合起來(lái)let str: String = "<HEAD>\n<TITLE>Ben Forta's Homepage</TITLE>\n<HEAD>" label.attributedText = textRegex(pattern: "(?<=<[tT][iI][tT][lL][eE]>).*(?=</[tT][iI][tT][lL][eE]>)" ,str: str, font: 18)說(shuō)明:眼睛尖銳的大家可能已經(jīng)看到了,上面我讀
<進(jìn)行了轉(zhuǎn)義,再?gòu)?qiáng)調(diào)一下,向前查找?=(不消費(fèi))和向后查找?<=(不消費(fèi))都是針對(duì)的子表達(dá)式來(lái)操作的。 -
9.4、對(duì)前后查找取非
各種前后取非操作符一般來(lái)說(shuō),凡是支持正向前查找的正則表達(dá)式也是支持負(fù)向前查找的,反之,凡是只是正向后查找的,也是支持負(fù)向后查找的。
對(duì)前后查找取非上面大家可能看到了
\b,單詞的邊界,去\b會(huì)有問(wèn)題的,有興趣的可以自己驗(yàn)證下。 -
9.5、總結(jié)
有了前后查找,我們就可以對(duì)最終的匹配結(jié)果包含哪些內(nèi)容做出更精確的控制。前后查找操作使我們可以利用子表達(dá)式來(lái)指定文本操作的發(fā)生位置,并收到只匹配不消費(fèi)的效果。正向前查找要用
(?=)來(lái)定義,負(fù)向前查找要用(?!)來(lái)定義。有些正則表達(dá)式實(shí)現(xiàn)還支持正向后查找(響應(yīng)的操作符是(?<=))和負(fù)向后查找(相應(yīng)的操作符是(?!<))。
十、嵌入條件
-
10.1、為什么要嵌入條件?(看下面的例子)
(123)456-7890和123-456-7890都是可以接收的北美電話號(hào)碼格式,而1234567890、(123)-456-789和(123-456-7890)雖然都包含著數(shù)字正確的字符,但是格式不對(duì),看下面的匹配
let str: String = "123-456-7890\n(123)456-7890\n(123)-456-7890\n(123-456-7890\n1234567890\n123 456 7890" label.attributedText = textRegex(pattern: "\\(?\\d{3}\\)?-?\\d{3}-\\d{4}" ,str: str, font: 24)分析:
\\(?匹配的是一個(gè)可選的左括號(hào), 請(qǐng)注意,這里必須對(duì)(進(jìn)行轉(zhuǎn)義;\d{3}匹配前三位數(shù)字;\)?匹配的是一個(gè)可選的右括號(hào);-?匹配的是一個(gè)可選的連字符
上面的匹配\\)?-如果換做[\\)-]?這樣的話)與-只能出現(xiàn)一個(gè)就能排除第三行,但是無(wú)法排除第4行,正確的匹配應(yīng)該是:只在電話號(hào)碼里有一個(gè)左括號(hào)(的時(shí)候才去匹配)。更準(zhǔn)確地說(shuō),應(yīng)該是如果電話號(hào)碼里有一個(gè)左括號(hào)(,我們的模式必須去匹配);如果不是這樣,它就必須去匹配-,總之這種匹配需要條件。 -
10.2、正則表達(dá)式里的條件
正則表達(dá)式里的條件要用
?來(lái)定義。事實(shí)上,你們已經(jīng)見(jiàn)過(guò)幾種非常特定的條件了。?匹配前一個(gè)字符或者表達(dá)式,如果它存在的話(可有可無(wú))。-
?=和?<=匹配前面或后面的文本,如果它存在的話。
嵌入條件語(yǔ)法也是用了?,這并沒(méi)有什么讓人感到吃驚的地方,因?yàn)榍度霔l件不外乎以下兩種情況。- 根據(jù)前一個(gè)回溯引用來(lái)進(jìn)行條件處理。
- 根據(jù)前后查找來(lái)進(jìn)行條件處理。
-
10.2.1、回溯引用條件
回溯引用條件只在一個(gè)前面的表達(dá)式搜索去的成功的情況下才允許使用一個(gè)表達(dá)式。看下面的例子,我們需要把一段文本里<IMG>標(biāo)簽全部都找出來(lái);不僅僅如此,如果某個(gè)<IMG>標(biāo)簽是一個(gè)鏈接(被括在<A>和</A>標(biāo)簽之間)的話,你還要把整個(gè)鏈接標(biāo)簽匹配出來(lái)。
用來(lái)定義這種條件的語(yǔ)法是(?(backrefence)truepregex),其中?表明這是一個(gè)條件,括號(hào)里的backrefence是一個(gè)回溯引用,truepregex是一個(gè)只在backrefence存在時(shí)才會(huì)被執(zhí)行的表達(dá)式。let str: String = "<!-- Nav bar -->\n<TD>\n<A HREF=/home><IMG SRC=/imges/home.gif></A>\n<IMG SRC=/images/spacer.gif>\n<A HREF=/search><IMG SRC=/imges/home.gif></A>\n</A>\n<IMG SRC=/images/spacer.gif>\n<A HREF=/help><IMG SRC=/imges/home.gif>\n</TD>" label.attributedText = textRegex(pattern: "(<[Aa]\\s+[^>]+>\\s*)?<[Ii][Mm][Gg]\\s+[^>]+>(?(1)\\s*</[Aa]>)" ,str: str, font: 24)分析:這個(gè)模式不解釋是不容易看明白的。
(<[Aa]\\s+[^>]+>\\s*)?將匹配一個(gè)<A>或<a>(以及<A>或<a>標(biāo)簽的任意屬性),這個(gè)標(biāo)簽可有可無(wú)(因?yàn)檫@個(gè)子表達(dá)式的最后有一個(gè)?)接下來(lái),<[Ii][Mm][Gg]\\s+[^>]+>匹配一個(gè)<IMG>(大小寫(xiě)均可)及其任意屬性。(?(1)\\s*</[Aa]>)是一個(gè)回溯引用條件,?(1)的含義是:如果第一個(gè)回溯引用條件(局具體到上面就是<A>標(biāo)簽)存在,則使用\s*</[Aa]>繼續(xù)進(jìn)行匹配(換句話說(shuō),只有當(dāng)前面的<A>標(biāo)簽匹配成功,才繼續(xù)進(jìn)行后面的匹配)。如果(1)存在,\s*</[Aa]>將匹配結(jié)束標(biāo)簽</A>之后出現(xiàn)的任意空白字符。
注意:(1)檢查第一個(gè)回溯引用是否存在,在條件里,回溯引用編號(hào)(本例中的1)不需要被轉(zhuǎn)義。因此,?(1)是正確的,?(\\1)不正確(但是也能用)。
我們剛才使用的模式只在給定的條件得到滿足時(shí)候才執(zhí)行一個(gè)表達(dá)式。條件還可以有否表達(dá)式,否則表達(dá)式只在給定的回溯引用不存在(也就是條件沒(méi)有得到滿足)時(shí)才會(huì)執(zhí)行。用來(lái)定義這種條件的語(yǔ)法是(?(backrefence)true-regex|false-regex),這個(gè)語(yǔ)法接受一個(gè)條件和兩個(gè)將分別在這個(gè)條件得到滿足和沒(méi)有得到滿足時(shí)執(zhí)行的表達(dá)式。(下面就可以解決上面10.1電話號(hào)碼的問(wèn)題)let str: String = "123-456-7890\n(123)456-7890\n(123)-456-7890\n(123-456-7890\n1234567890\n123 456 7890" label.attributedText = textRegex(pattern: "(\\()?\\d{3}(?(1)\\)|-)\\d{3}-\\d{4}" ,str: str, font: 24)
分析:從結(jié)果上看,這個(gè)模式解決了問(wèn)題,但它是如何解決問(wèn)題呢?和前面一樣,
(\\()?也匹配一個(gè)可選的左括號(hào),但我們這次把它用括號(hào)括起來(lái)得到一個(gè)子表達(dá)式。隨后的\d{3}匹配一位數(shù)字的區(qū)號(hào)。(?(1)\\)|-)是一個(gè)回溯引用條件,它將根據(jù)條件是否得到滿足而去匹配)或-:如果(1)存在(也就是找到了一個(gè)左括號(hào)),\\)必須被匹配;否則,-必須被匹配。這樣一來(lái),只有配對(duì)出現(xiàn)的括號(hào)才會(huì)被匹配;如果沒(méi)有使用括號(hào)或括號(hào)不配對(duì),電話號(hào)碼中的區(qū)域和其余數(shù)字之間的-必須被匹配。 -
10.2.2、前后查找條件
前后查找條件只在一個(gè)向前查找或向后查找操作取得成功的情況下才允許一個(gè)表達(dá)式被使用。定義一個(gè)前后查找條件的語(yǔ)法與定義一個(gè)回溯引用的條件的語(yǔ)法大同小異,只需要把回溯引用(括號(hào)里的回溯引用標(biāo)號(hào))替換為一個(gè)完整的前后查找表達(dá)式就行了。
-
例子一美國(guó)郵政編碼匹配
let str: String = "11111\n22222\n33333-\n44444-4444" label.attributedText = textRegex(pattern: "\\d{5}(-\\d{4})?" ,str: str, font: 24)上面例子的更正:
let str: String = "11111\n22222\n33333-\n44444-4444" label.attributedText = textRegex(pattern: "\\d{5}(?(?=-)-\\d{4})" ,str: str, font: 24)分析:
\d{5}匹配前五位數(shù)字,接下來(lái)是一個(gè)(?(?=-)-\\d{4})形式的向前查找條件。這個(gè)條件使用了?=-來(lái)匹配(但不消費(fèi))一個(gè)連字符,如果條件得到滿足(那個(gè)連字符存在),-\\d{4}將匹配那個(gè)連字符和隨后的4位數(shù)字。這樣一來(lái),33333-將被排除在最終的匹配結(jié)果之外(它有一個(gè)連字符,所以滿足給定的條件,但那個(gè)連字符后面沒(méi)有必須出現(xiàn)在那里的4位數(shù)字)。平時(shí)工作中嵌入查找的模式相當(dāng)少見(jiàn),這是因?yàn)槲覀兺梢杂米詈?jiǎn)單的辦法來(lái)達(dá)到同樣的目的。
-
-
10.3、總結(jié)
在正則表達(dá)式里面可以嵌入條件,只有相當(dāng)條件得到(或者沒(méi)有得到)滿足時(shí),相應(yīng)的表達(dá)式才會(huì)被執(zhí)行。這種條件可以是一個(gè)回溯引用(含義是檢查該回溯引用是否存在),也可以是一個(gè)前后查找的操作。
十一、元字符表
-
11.1、基本的元字符
-
.匹配任意單個(gè)字符 -
|邏輯或操作符 -
[]匹配字符集合中的一個(gè)字符 -
[^]對(duì)集合求非 -
-定義一個(gè)區(qū)間,如[a-z] -
\對(duì)下一個(gè)字符轉(zhuǎn)義
-
-
11.2、數(shù)量元字符
-
*匹配前一個(gè)字符(子表達(dá)式)零次或者多次 -
*?是*的懶惰型版本 -
+匹配前一個(gè)字符(子表達(dá)式)的一次或多次重復(fù) -
+?是+的懶惰型版本 -
?前一個(gè)字符可以可無(wú),也就是最多匹配一次 -
{n}匹配前一個(gè)字符或者表達(dá)式n次 -
{m,n}匹配前一個(gè)字符或表達(dá)式最少m次,最多n次 -
{m,}匹配前一個(gè)字符至少m次 -
{m,}?{m,}的懶惰型版本
-
-
11.3、位置元字符
-
^匹配字符串的開(kāi)頭 -
\A匹配字符串的開(kāi)頭 -
$匹配字符串的結(jié)束 -
\z匹配字符串的結(jié)束 -
\<單詞匹配的開(kāi)始 -
\>單詞匹配的結(jié)束 -
\b單詞匹配的邊界(開(kāi)頭和結(jié)束) -
\B是\b的反義
-
-
11.4、特殊字符元字符
-
[\b]退格字符 -
\c匹配一個(gè)控制字符 -
\d匹配任意數(shù)字字符 -
\D匹配任意非數(shù)字字符 -
\f換頁(yè)符 -
\n換行符 -
\r回車符 -
\s匹配一個(gè)空白字符 -
\S匹配一個(gè)非空白字符 -
\t制表符(Tab字符) -
\v垂直制表符 -
\w匹配任意數(shù)字、字母、下劃線以及中文漢字 -
\W匹配任意非數(shù)字、非字母、非下劃線以及非中文漢字 -
\x匹配一個(gè)十六進(jìn)制數(shù)字 -
\0匹配一個(gè)八進(jìn)制數(shù)字
-
-
11.5、回溯引用和前后查找
-
()定義一個(gè)子表達(dá)式 -
\1匹配第一個(gè)子表達(dá)式\2代表匹配第二個(gè)子表達(dá)式 -
?=向前查找 -
?<=向后查找 -
?!負(fù)向前查找 -
?<!負(fù)向后查找 -
?()條件 (if then) -
?()|條件(if then else)
-
11.6、大小寫(xiě)轉(zhuǎn)換
\E結(jié)束\L或\U轉(zhuǎn)換\l把下一個(gè)字符轉(zhuǎn)換為小寫(xiě)\L把后面的字符轉(zhuǎn)換為小寫(xiě)直到遇見(jiàn)\E為止\u把下一個(gè)字符轉(zhuǎn)換為大寫(xiě)\U把后面的字符轉(zhuǎn)換為大寫(xiě)直到遇見(jiàn)\E為止-
11.7、匹配模式
-
(?m)分行匹配模式
-
十二、多規(guī)則匹配
-
主要闡述多規(guī)則匹配的用法
let pattern = pattern1 + "|" + pattern2 + "|" + pattern3看下面let str = "@joanking:【周杰倫的歌曲】#大眼睛#小貓咪這么尖叫[偷笑]、@老北: 蟬叫、狼這么尖叫[吃驚]、@樂(lè)不思蜀:達(dá)芬奇#燒餅#妙的笑到最后[挖鼻屎]!~ http://www.baidu.com" do{ // 1.創(chuàng)建規(guī)則 let pattern1 = "\\[.*?\\]" let pattern2 = "@.*?:" let pattern3 = "#.*?#" // 多個(gè)規(guī)則之間使用 | 符號(hào)連接 let pattern = pattern1 + "|" + pattern2 + "|" + pattern3 // 2.創(chuàng)建正則表達(dá)式對(duì)象 let regex = try NSRegularExpression(pattern: pattern, options: NSRegularExpression.Options.caseInsensitive) // 3.開(kāi)始匹配 let res = regex.matches(in: str, options: NSRegularExpression.MatchingOptions(rawValue: 0), range: NSMakeRange(0, str.count)) // 4取出結(jié)果 for checkingRes in res { // print(checkingRes.range) print((str as NSString).substring(with: checkingRes.range)) } }catch { print(error) }
十三、正則練習(xí)的demo(有心的人可以看看,可以一起討論一下回溯引用方面的知識(shí),自己理解的不是很好)
- 測(cè)試用的JKRegexdemo
記得給個(gè)喜歡??

















































