9、正則表達式與JSON

正則表達式:一個特殊的字符序列,可以幫助檢測一個字符串是否與我們所設定的字符序列相匹配。

功能:可以實現快速檢索文本、替換文本的操作。

  • 檢測一串數字是否是電話號碼
  • 檢測一個字符串是否符合e-mail格式
  • 把一個文本里指定的單詞替換為另外一個單詞
#不使用正則表達式的操作
a = 'C|C++|Java|Python'
#index()函數,如果 'a' 中含有 'Python' 就會返回 'Python' 首個字符的位置,否則報錯。
print(a.index('Python'))
結果:11
#同樣可以使用 in 函數 
print('Python' in a)
結果:True
#用正則表達式處理:
import re  #正則表達式操作函數集

a = 'C|C++|Java|Python'
#findall():第一個參數為要查詢的字符串,第二個參數為被查詢的字符串。
#函數返回查詢到的全部的字符串所構成的列表
r = re.findall('Python',a) 
if len(r) > 0:
    print(r)
else:
    print('No')

結果: ['Python']

元字符與普通字符

#提取字符串中所有的數字:
import re

a = 'C2C++4Java7Python6'
r = re.findall('\d',a)
print(r)

結果:['2', '4', '7', '6']

\d:表示所有數字
‘Python’普通字符,'\d'元字符。

正則表達式就是由一系列普通字符和元字符組成的。

#提取字符串中所有的非數字:
import re

a = 'C2C++4Java7Python6'
r = re.findall('\D',a)    #\D為非數字
print(r)

結果:['C', 'C', '+', '+', 'J', 'a', 'v', 'a', 'P', 'y', 't', 'h', 'o', 'n']

字符集

#判斷中間是一個字符c或f的單詞:
import re

s = 'abc,acc,adc,aec,afc,ahc'
#[]:字符集,或關系
r = re.findall('a[cf]c',s) 
print(r)

結果:['acc', 'afc']
[]:字符集,或關系。[cf],c或f

普通字符用于定界,確定某一個小段

#判斷中間是一個不是c或f的字符的單詞:
import re

s = 'abc,acc,adc,aec,afc,ahc'
r = re.findall('a[^cf]c',s) 
print(r)

結果:['abc', 'adc', 'aec', 'ahc']
^:取反操作
#利用字符順序省略字符,匹配c,d,e,f:
import re

s = 'abc,acc,adc,aec,afc,ahc'
r = re.findall('a[c-f]c',s)
print(r)

結果:['acc', 'adc', 'aec', 'afc']
-:省略中間字符

概括字符集

\d可以用[0-9]表示:
import re

a = 'python1111java678php'
r = re.findall('[0-9]',a)
print(r)

結果:['1', '1', '1', '1', '6', '7', '8']
\w匹配單詞字符,也就是[A-Za-z0-9_]
import re

a = 'python1111&_java678  \nph\rp'
r = re.findall('\w',a)  #等價于r = re.findall('[A-Za-z0-9_]',a)
print(r)

結果:['p', 'y', 't', 'h', 'o', 'n', '1', '1', '1', '1', '_', 'j', 'a', 'v', 'a', '6', '7', '8', 'p', 'h', 'p']
  • \W 只匹配非單詞字符,如空格、&、\n、\r等都為非單詞字符。
  • \s 代表空白字符:空格、\n、\r等。
  • \S 匹配所有非空白字符
import re

a = 'python1111&_java678 \nph\rp'
r = re.findall('\s',a)
print(r)

結果:[' ', '\n', '\r']

常用的概括字符集:\d \D \w \W \s \S
'.' 匹配除換行符\n之外的其他所有字符

數量詞

匹配三個字母的單詞:
import re

a = 'python1111 java678php'
r = re.findall('[a-z]{3}',a)

print(r)
結果:['pyt', 'hon', 'jav', 'php']

匹配完整的單詞:
import re

a = 'python1111 java678php'
r = re.findall('[a-z]{3,6}',a)  #3,4,5,6個為一組
print(r)

結果:['python', 'java', 'php']

利用數量詞 {} 多次重復
r = re.findall('[a-z]{3}',a) 也可以寫成 r = re.findall('[a-z][a-z][a-z]',a)

貪婪與非貪婪

數量詞有貪婪和非貪婪之分,一般來說Python傾向于貪婪的匹配方式。
python會盡可能匹配到最大的字符串。

{number} ?變成非貪婪模式,此時python會匹配最小的字符串
import re

a = 'python1111 java678php'
r = re.findall('[a-z]{3,6}?',a)
print(r)

結果:['pyt', 'hon', 'jav', 'php']

匹配次數

用*匹配*之前字符0次或者無限多次:
import re

a = 'pytho0python1pythonn2'
r = re.findall('python*',a)
print(r)
結果:['pytho', 'python', 'pythonn']

用+匹配一次或者無限多次:
import re

a = 'pytho0python1pythonn2'
r = re.findall('python+',a)
print(r)
結果:['python', 'pythonn']

用?匹配0次或者一次:
import re

a = 'pytho0python1pythonn2'
r = re.findall('python?',a)
print(r)

結果:['pytho', 'python', 'python']
可以用?來進行去重復的操作。

注意:{3,6}?和 python? 的問號用法不一樣。

邊界匹配符

QQ號的位數是否符合4-8位:
import re

qq = '10000004531'
r = re.findall('^\d{4,8}$',qq)
print(r)

結果:[]
^, $ 組成邊界匹配符
^:從字符串開頭開始匹配
$:從字符串末尾開始匹配

000$:匹配最后三位是000,^000:匹配開始三位是000

python字符串是否重復出現三次:
import re

a = 'pythonpythonpythonpythonpython'
r = re.findall('(python){3}',a)
print(r)

結果:['python']
() 對應一組字符

[ ]里的字符是 或關系,[A-Z]表示匹配一個字符是否為大寫字母
()里的字符是 且關系,(A-Z)表示匹配一個字符串 'abcd...xyz'

匹配模式參數

re.findall()的第三個參數為模式

忽略大小寫:
import re

a = 'pythonC#\nJavaPHP'
r = re.findall('c#',a, re.I | re.S)
print(r)

結果:['C#']
re.I:忽略大小寫
re.S:匹配包括\n在內的任意字符
多個模式之間用 '|' ,這里的 '|' 是且的關系。

re.sub正則替換

re.sub(), 五個參數(要替換的匹配表達式,替換成的字符串,被替換的字符串,替換次數,替換模式)

查找并替換:
import re

a = 'PythonC#\nJavaPHP'
r = re.sub('C#','GO',a,0)    
#0:把所有的C#換成GO,1:只有第一個匹配到的被替換成GO
print(r)

結果:PythonGO
     JavaPHP
常規替換可以使用replace函數:
import re

a = 'PythonC#\nJavaPHP'
a = a.replace('C#','GO')    #是sub的簡化版,替換所以的C# 為 GO
print(a)

結果:PythonGO
     JavaPHP
sub強大的地方在于其第二個參數可以是一個函數:
import re

def convert(value):
    #此時的value是一個JSON格式,包含了字符串的其他信息
    matched = value.group()    #從對象中提取字符串
    return '!!' + matched + '!!'

a = 'PythonC#JavaPHP'
r = re.sub('C#',convert,a)
print(r)

結果:Python!!C#!!JavaPHP
sub匹配到的字符串后會被傳到convert函數中,返回新的字符串來替換匹配到的詞。

把函數作為參數傳遞

找出數字,大于等于6的替換成9,小于6的替換成0:
import re

def convert(value):
    matched = value.group()
    if int(matched) >= 6:
        return '9'
    else:
        return '0'

s = 'A8C3721D86'
r = re.sub('\d',convert,s)
print(r)

結果:A9C0900D99
使用函數修改字符串的方式很靈活。

search與match函數

match:從字符串開始的地方開始匹配(首字母開始匹配)。
search:搜索整個字符串,直到找到第一個滿足的結果并返回。

import re

s = 'A8C3721D86'
r = re.match('\d',s)
print(r)

r1 = re.search('\d',s)
print(r1)

結果 r:None

結果 r1:<re.Match object; span=(1, 2), match='8'>
r1.group()  返回字符串的值
r1.span()   返回位置的位置

match和search返回的是對象,且只匹配一次,不會像findall一樣匹配所有。

group分組

提取life和python之間的字符: 
import re

s = 'life is short,i use python'
r = re.search('life(.*)python',s)
print(r.group(0))
print(r.group(1))
結果:life is short,i use python
      is short,i use

group(0)是匹配全部內容
group(1)是只提取中間的部分(看分組的數量,第一個就是1,第n個就是n)


import re

s = 'life is short,i use python,i love python'
r = re.search('life(.*)python(.*)python',s)
print(r.group(0))
print(r.group(1))
print(r.group(2))
結果 0:life is short,i use python,i love python
結果 1:is short,i use
結果 2:,i love


r.groups()返回除完整匹配以外的所有結果:
import re

s = 'life is short,i use python,i love python'
r = re.search('life(.*)python(.*)python',s)
print(r.groups())
結果:(' is short,i use ', ',i love ')

JSON

JavaScript Object Notation, 是一種輕量級(與XML比)的數據交換格式。
JSON適合做中間語言,進行跨語言交換數據。

JSON應用:前后端分離的數據傳輸
REST服務的標準格式:JSON。

字符串是JSON的表現形式,符合JSON格式(類似于Python的字典)的字符串就是JSON字符串。

反序列化

反序列化:字符串 -> 語言下某一數據結構的過程

利用python內部的json解析JSON數據:
import json

json_str = '{"name":"tai","age":23}'    #json內用雙引號,則外部用單引號表示str
student = json.loads(json_str)  #將json格式的數據轉換成python格式的數據
print(type(student))
print(student)
print(student['name'])

結果 type(student):<class 'dict'>    #解析出來是字典
結果 student:{'name': 'tai', 'age': 23}
結果 student['name']:tai


同樣的JSON字符串,不同的語言會裝換成不同的類型。其中對應到Python中是字典類型。

 
解析JSON數組:
import json

json_str = '[{"name":"tai","age":23,"flag":false},{"name":"tai","age":23}]'
student = json.loads(json_str) 
print(type(student))
print(student)

結果 type(student):<class 'list'>    #數組轉成了列表
結果 student:[{'name': 'tai', 'age': 23, 'flag': False}, {'name': 'tai', 'age': 23}] 

json和python的數據轉換列表

JSON Python
object dict
array list
string str
number int(float)
true True
false False
null None

序列化:

import json

student = [{"name":"tai","age":23,"flag":False},{"name":"tai","age":23}]
json_str = json.dumps(student)  #將python數據類型轉換成JSON數據
print(type(json_str))
print(json_str)

結果 type(json_str):<class 'str'>
結果 json_str:[{"name": "tai", "age": 23, "flag": false}, {"name": "tai", "age": 23}]
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,237評論 6 537
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,957評論 3 423
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,248評論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,356評論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,081評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,485評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,534評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,720評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,263評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,025評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,204評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,787評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,461評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,874評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,105評論 1 289
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,945評論 3 395
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,205評論 2 375

推薦閱讀更多精彩內容