Python進階1 - 正則表達式: 轉(zhuǎn)義字符與原始字符串詳解

這邊文章默認使用了富文本編輯器,請到另一篇相同內(nèi)容的MarkDown編輯過的內(nèi)容中查看,連接如下

Python中的轉(zhuǎn)義字符與原始字符串詳解


小馬哥在使用正則表達式面對轉(zhuǎn)義字符的時候,發(fā)現(xiàn)字符串的轉(zhuǎn)義與正則的轉(zhuǎn)義有沖突的時候,總是有些不難,但是讓人感覺沒規(guī)律的地方,于是就專門研究了一下,首先捋一下知識點,約定一個前提概念:

轉(zhuǎn)義字符: 屬于字符串的概念,作用于打印. 例如,要完成一個退格,一個制表符,一個換行,這個用字符串如何表示?

? ? 簡單,"\b,\t,\n",不過是用"\"來轉(zhuǎn)義一下普通字符嘛,是的,因為b,t,n是普通字符,如果直接輸出,當然就是字符,于是加上"\",打印的時候就是另一種意思了,這個打印,可以是輸出到屏幕,也可以是其它輸出

正則表達式中的轉(zhuǎn)義: 看到這里,你會想起,正則里面好像也有轉(zhuǎn)義的概念,例如,"."代表匹配字符串里面的任意字符(換行符除外),如果需要匹配真正的"."這個字符怎么辦?于是我們用轉(zhuǎn)義字符"\."就代表匹配字符串中的"."了.

你有沒有想過這個問題,字符串中的轉(zhuǎn)義和正則中的轉(zhuǎn)義不是一套概念體系,如果兩者沒有表達上的沖突,那么相安無事,可是狀況恰恰是有沖突的,"\b"在字符串中表示轉(zhuǎn)義后的結(jié)果: 退格;而在正則中代表匹配目標字符串的邊界. 于是就要想辦法解決沖突: 定義了原始字符串來屏蔽掉沖突.

只看說明,你還是一頭蒙的,那么看例子來闡述一遍上面所有的問題:

```python

# 字符串中的轉(zhuǎn)義: 斜杠\代表轉(zhuǎn)義字符,\b代表轉(zhuǎn)義之后的字符串,是退格

data = '123\b456'

# 顯示一下結(jié)果

print(data)? ? #發(fā)現(xiàn)被轉(zhuǎn)義后: 12456

data = '123\n456'

print(data)? ? #換行: 就是通過轉(zhuǎn)義符把n進行轉(zhuǎn)義表示回車

```

? ? 123456

? ? 123

? ? 456


如上還有\(zhòng)t制表符也是同樣的意思,這些,都是來自于ASCII對字符的規(guī)定,記住: 這些屬于字符串中的轉(zhuǎn)義

下面看看正則的轉(zhuǎn)義

```python

import re

print('第一次試驗')

data = 'hello1 python,hello2 java'

pattern = '\bhello.'

result = re.findall(pattern,data)

print(result)

'''

分析:

這個時候的正則表達式模式,沒有匹配到期望的hello1與hello2,因為\b這里代表的不是正則的邊界

1,pattern = '\bhello.',首先是一個字符串,就要接受字符串的處理,

? ? 根據(jù)ASCII表,\b是退格,是一個看不到的字符,所以'\b'是一個字符,hello是另外的字符,

2,我們期望的正則模式是: '邊界hello.',這個"邊界"的表示方法和字符的ASCII碼沖突,沒有體現(xiàn)出來

于是,清楚了原因,我們應該設(shè)計一個模式,在經(jīng)歷字符串ASCII解析后,再傳遞給正則引擎之后是\bhello

應該這樣寫: '\\bhello'

'''

print('第二次試驗')

data = 'hello1 python,hello2 java'

pattern = '\\bhello.'? #這時,經(jīng)過字符的ASCII表解析后,得到的字符串是'\bhello'

result = re.findall(pattern,data)

print(result)

'''

到此,你心里應該有了一個: 計算機內(nèi)部針對 字符 - ->模式 的過程

不是你寫了一個字符串,它就是正則的模式了,而是計算機內(nèi)部要根據(jù)ASCII碼進行了解析,解析的結(jié)果,拿給了正則引擎去用來搜索目標文本,

而ASCII碼解析后的結(jié)果,和你期望的正則的模式發(fā)生變化了,所以正則表達式解析來的結(jié)果,不如我們期望的

'''

```

? ? 第一次試驗

? ? []

? ? 第二次試驗

? ? ['hello1', 'hello2']


如果通過上面的例子,你懂了ASCII碼在暗中干了一件'見不得人'的事,如果你的腦力還夠用,那么咱們再來看一個它的更有意思的事情

需求: 'python\java\go\c',解析出里面的"\",在字符概念領(lǐng)域,它是轉(zhuǎn)義字符,在正則領(lǐng)域,它也是轉(zhuǎn)義字符,如何操作呢?

上面,我們主要目的:讓你知道,ASCII碼和正則,針對轉(zhuǎn)義是不同的,有沖突的,例如,\b在兩者概念體系中就沖突了,

```python

import re

data = 'python\java\go\c'

'''

pattern1

這個都不用試驗,肯定是錯的,語法錯誤,解析都通不過,相當于,你想打印" ' "單引號,但是字符串的定義就是用單引號或者雙引號來表示

\'相當于失去了字符串"'"的定義作用,而把"'"看做普通字符,那么這樣,字符串的pattern1,就沒有了字符串的結(jié)尾符了,必然錯誤

'''

# pattern1 = '\'? #必須注釋了,語法都通不過檢查

'''

pattern2

用上一個例子中分析的結(jié)果,我們用轉(zhuǎn)義字符把斜杠處理過,得到就是ASCII處理后的"\",再拿去交給正則引擎,這個時候正則我們應該沒問題了

的確,這里經(jīng)過ASCII碼處理,最終交給正則的是"\",這個時候就該正則引擎起作用了,對于它"\"也是一個轉(zhuǎn)義符,可只要\這是一個不完整的轉(zhuǎn)義

于是拋出error: bad escape (end of pattern) at position 0

'''

try:

? ? pattern2 = '\\'? ?

? ? print(pattern2)

? ? result2 = re.findall(pattern2,data)

? ? print(result2)

except Exception as e:

? ? print("Error: ",e)

'''

pattern3

我們應該傳遞給正則解析引擎一個"\\",經(jīng)過正則處理,它會得到"\"這個僅僅代表字符的模式,拿著去和目標文本比對,搜索目標"\"

'\\\\'經(jīng)過ASCII碼處理,得到"\\",正則引擎處理'\\',得到'\'

'''

pattern3 = '\\\\'

result3 = re.findall(pattern3,data)

print(result3)

```

? ? \

? ? Error:? bad escape (end of pattern) at position 0

? ? ['\\', '\\', '\\']


經(jīng)過上面兩個例子:

例一,你應該明白了,一個字符串能作為正則的模式,中間是經(jīng)過ASCII碼轉(zhuǎn)換的,但是為什么"\d","\w"等就相安無事呢?因為ASCII碼沒"整"它們;

例二,對于"\"這種比較特殊的東東,經(jīng)過ASCII和正則的兩次轉(zhuǎn)義,語法都要正確,才能去匹配目標文本中的目標字符

有沒有一種方式,不用這么麻煩,于是出現(xiàn)了原始字符串.

看例三,原始字符串的用法

```python

import re

data = 'python\java\go\c'

pattern = r'\\'? ? ? #這里為什么還要是兩個斜杠呢? 畢竟這里是字符串的定義

print(pattern)

result = re.findall(pattern,data)

print(result)

data = 'hello1 java,hello2 python'

pattern = r'\bhello.'? ? #這里就去掉了\b的退格作用

print(pattern)

result = re.findall(pattern,data)

print(result)

```

? ? \\

? ? ['\\', '\\', '\\']

? ? \bhello.

? ? ['hello1', 'hello2']


可能有的同學有疑問: 為什么上面打印的result關(guān)于findall結(jié)果的地方,result列表里面都是'\\',其實'\\'代表的是一個字符'\\',print()打印這個動作就變成'\'了.不信去試試.


這邊文章默認使用了富文本編輯器,請到另一篇相同內(nèi)容的MarkDown編輯過的內(nèi)容中查看,連接如下

Python中的轉(zhuǎn)義字符與原始字符串詳解

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末陷虎,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子煌珊,更是在濱河造成了極大的恐慌,老刑警劉巖轨蛤,帶你破解...
    沈念sama閱讀 206,839評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件厅各,死亡現(xiàn)場離奇詭異,居然都是意外死亡旧巾,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評論 2 382
  • 文/潘曉璐 我一進店門忍些,熙熙樓的掌柜王于貴愁眉苦臉地迎上來鲁猩,“玉大人,你說我怎么就攤上這事罢坝∩龋” “怎么了?”我有些...
    開封第一講書人閱讀 153,116評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長疾棵。 經(jīng)常有香客問我戈钢,道長,這世上最難降的妖魔是什么是尔? 我笑而不...
    開封第一講書人閱讀 55,371評論 1 279
  • 正文 為了忘掉前任殉了,我火速辦了婚禮,結(jié)果婚禮上拟枚,老公的妹妹穿的比我還像新娘薪铜。我一直安慰自己,他們只是感情好恩溅,可當我...
    茶點故事閱讀 64,384評論 5 374
  • 文/花漫 我一把揭開白布隔箍。 她就那樣靜靜地躺著,像睡著了一般脚乡。 火紅的嫁衣襯著肌膚如雪蜒滩。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,111評論 1 285
  • 那天奶稠,我揣著相機與錄音俯艰,去河邊找鬼。 笑死锌订,一個胖子當著我的面吹牛竹握,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播辆飘,決...
    沈念sama閱讀 38,416評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼啦辐,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了蜈项?” 一聲冷哼從身側(cè)響起昧甘,我...
    開封第一講書人閱讀 37,053評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎战得,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體庸推,經(jīng)...
    沈念sama閱讀 43,558評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡常侦,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,007評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了贬媒。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片聋亡。...
    茶點故事閱讀 38,117評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖际乘,靈堂內(nèi)的尸體忽然破棺而出坡倔,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 33,756評論 4 324
  • 正文 年R本政府宣布罪塔,位于F島的核電站投蝉,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏征堪。R本人自食惡果不足惜瘩缆,卻給世界環(huán)境...
    茶點故事閱讀 39,324評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望佃蚜。 院中可真熱鬧庸娱,春花似錦、人聲如沸谐算。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽洲脂。三九已至斤儿,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間腮考,已是汗流浹背雇毫。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留踩蔚,地道東北人棚放。 一個月前我還...
    沈念sama閱讀 45,578評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像馅闽,于是被迫代替她去往敵國和親飘蚯。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,877評論 2 345

推薦閱讀更多精彩內(nèi)容