日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

网络工程师——正则表达式(模糊匹配)

發布時間:2023/12/10 编程问答 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 网络工程师——正则表达式(模糊匹配) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

網絡工程師——正則表達式(模糊匹配)

(本博客借鑒《網絡工程師的python之路這本書》

1.什么是正則表達式

??正則表達式,又稱規則表達式,計算機科學的一個概念。正則表達式通常被用來檢索、替換那些符合某個模式(規則)的文本。
  許多程序設計語言都支持利用正則表達式進行字符串操作。例如,在Perl中就內建了一個功能強大的正則表達式引擎。正則表達式這個概念最初是由Unix中的工具軟件(例如sed和grep)普及開的。正則表達式通常縮寫成“regex”,單數有regexp、regex,復數有regexps、regexes、regexen。
(來源百度百科)

2.正則表達式的規則(模糊匹配)

匹配符號用法
.匹配除換行符之外的所有字符(一次)
*用來匹配緊靠該符號左邊的符號,匹配次數0次或多次。
+用來匹配緊靠該符號左邊的符號,匹配次數1次或多次。
用來匹配緊靠該符號左邊的符號,匹配次數0次或1次。
{m}用來匹配緊靠該符號左邊的符號,指定匹配次數為m次,例如字符串’abbbbcccd’,使用ab{2}將匹配到abb,使用bc{3}d將匹配到bcccd。
{m,n}用來匹配緊靠該符號左邊的符號,指定匹配次數為最少m次,最多n次。 例如字符串’abbcccd’,使用ab{2,3}將只能匹配到abb,如果字符串為’abbbbcccdabbccd’,使用ab{2,3}將能同時匹配到abbb和abb。如果字符串內容為’abcd’使用ab{2,3}將匹配不到任何東西。
{m,}用來匹配緊靠該符號左邊的符號,指定匹配次數為最少m次,最多無限次。
{,n}用來匹配緊靠該符號左邊的符號,指定匹配次數為最少0次,最多n次。
\例如字符串內容中出現了問號"?”,而你又想精確匹配這個問號,那就要使用?來進行匹配。除此之外,\也用來表示一個特殊序列。
[]表示字符集合,用來精確匹配。比如想要精確匹配一個數字,可以使用[0-9]。如果要精確匹配一個小寫字母,可以用[a-z],如果要精確匹配一個大寫字母,可以用[A-Z],如果要匹配一個數字、字母或者下劃線,可以用[0-9a-zA-Z_]。另外在[]中加^表示取非,比如[^O-9]表示匹配一個非數字的字符,[^a-z]表示匹配一個非字母的字符,以此類推。
|表示或匹配(兩項中匹配其中任意一項),比如要匹配FastEthernet和GigabitEthernet這兩種端口名,可以寫作Fa|Gi。
(…)組合,匹配括號內的任意正則表達式,并標識出組合的開始和結尾,例如(blcd)ef表示bef或cdef。
\d匹配任意一個十進制數字,等價于[0-9]
\Dld取非,匹配任意一個非十進制數字,等價于[^0-9]
\w匹配任意一個字母,十進制數字以及下劃線,等價于[a-zA-Z0-9_]
\W匹配任意個一個空白字符,包括空格,換行符\n等等。
\s匹配任意個一個空白字符,包括空格,換行符\n等等。

在使用表達式之前一定要先import re

2.1[]的應用

>>> re.match('a[a-z]c',`在這里插入代碼片`'abc') <re.Match object; span=(0, 3), match='abc'>匹配a-z之間任意字符 >>> re.match('a[a-z]c','a1c') >>> re.match('a[0-9]c','a1c') <re.Match object; span=(0, 3), match='a1c'>匹配0-9之間任意字符 >>> re.match('a[^a-z]c','a1c') <re.Match object; span=(0, 3), match='a1c'>匹配除了a-z之間任意

2.2* ?()的應用

>>> re.match('ba(na)?','ba') <re.Match object; span=(0, 2), match='ba'> >>> re.match('ba(na)?','bana') <re.Match object; span=(0, 4), match='bana'> >>> re.match('ba(na)?','banana') <re.Match object; span=(0, 4), match='bana'> >>> re.match('ba(na)*','ba') <re.Match object; span=(0, 2), match='ba'> >>> re.match('ba(na)*','bana') <re.Match object; span=(0, 4), match='bana'> >>> re.match('ba(na)*','banana') <re.Match object; span=(0, 6), match='banana'>總結:? 01 * 0或無窮

2.3 |的應用

>>> re.match('root|Root','root') <re.Match object; span=(0, 4), match='root'> >>> re.match('root|Root','Root') <re.Match object; span=(0, 4), match='Root'>

2.4貪婪匹配

??*, +,?,{m}, {m,}, {m,n}這六種匹配符號默認都是貪婪匹配的,即會盡可能多的去匹配符合條件的內容。舉例如下:
舉例如下:
??假設給定的字符串為’xxzyzyz’,我們使用正則表達式x.*y來做匹配(注:精確匹配和模糊匹配可以混用)。在匹配到第一個x后,開始匹配.*,因為.和*默認是貪婪匹配,這里它會一直往后匹配,直到匹配到最后一個y,因此這里的匹配結果為xxzyzy。

(測試網站為https://regex101.com/)

2.5非貪婪匹配

??要實現非貪婪匹配很簡單,就是在上述六種貪婪匹配符號后面加上問號?即可,也即是*?, +?, ??, {m}?, {m,}?, {m,n}?。
因為.*?是非貪婪匹配,這里它在匹配到第一個y后便隨即停止,因此這里的匹配結果為xxzy。
?可以認為是對于?后面的字符生效,只要匹配到一次?后面的字符就結束匹配

2.6實例

匹配思科交換機中日志類型\w{1,9}-\d-\w{6,13}

000459: Feb 17 17:10:35.202: %LINK-3-UPDOWN: Interface FastEthernet0/2, changed state to up 000460: Feb 17 17:10:36.209: %LINEPROTO-5-UPDOWN: Line protocol on Interface FastEthernet0/2, changed state to up 000461: Feb 17 22:39:26.464: %SSH-5-SSH2_SESSION: SSH2 Session request from 10.1.1.1 (tty = 0) using crypto cipher 'aes128-cbc', hmac 'hmac-sha1' Succeeded 000462: Feb 17 22:39:27.748: %SSH-5-SSH2_USERAUTH: User 'test' authentication for SSH2 Session from 10.1.1.1 (tty = 0) using crypto cipher 'aes128-cbc', hmac 'hmac-sha1' Succeeded

用LINK-3-UPDOWN舉例

%:匹配% w{1,9}:匹配 link -:匹配- \d:匹配3 w{6,13}:匹配 UPDOWN

3 各種方法

3.1 re.mach()

(前文已經用過了)
??這里我們使用re.match()函數,從字符" Test match() function of regular expression. "里去精確匹配模式’Test’,因為’Test’位于該段字符串的起始位置,所以匹配成功,并且返回了一個匹配到的對象<re.Match object; span=(0, 4), match=‘Test’>,為了查看該對象的具體的值,我們可以對該對象調用group()方法,得到具體的值’Test’,該值的數據類型為字符串。

import re test='Test match() function or regular expression.' a=re.match(r"Test",test) print(a) print(a.group())

輸出:

<re.Match object; span=(0, 4), match='Test'> Test

??如果這里我們不從字符串的起始位置去匹配,而是去匹配中間或末尾的字符串內容的話,那么re.match()將匹配不到任何東西,從而返回None,比如這里我們去匹配’function’這個詞,因為function不在’Test match() function of regular expression.'這句字符串的開頭所以這里re.match()返回的值為None。

import re test='Test match() function or regular expression.' a=re.match(r"function",test) print(a) print(a.group())

輸出

None

re.match 必須從開頭匹配
a=re.match(r"function",test)中的r什么意思?意思是“ ”中的是原始字符串,總之在正則表達式中,建議都使用原始字符串。

3.2 re.search()

import re test='Test match() function or regular expression.' a=re.search(r"function",test) print(a) print(a.group())

輸出:

<re.Match object; span=(13, 21), match='function'> function

re.search方法可以匹配字符串中的任意位置的內容。

但是它和re.match()一樣一次只能匹配到一個字串內容,比如下面是某臺路由器上show ip int brief的輸出結果,我們希望用正則表達式來匹配到在該輸出內容中出現的所有IPv4地址:

R6#sh ip int br Interface IP-Address OK? Method Status Protocol FastEthernet0/0 192.168.1.1 YES manual up up FastEthernet1/0 192.168.2.1 YES manual up up FastEthernet2/0 192.168.3.1 YES manual up up import re ip='''R6#sh ip int br Interface IP-Address OK? Method Status Protocol FastEthernet0/0 192.168.1.1 YES manual up up FastEthernet1/0 192.168.2.1 YES manual up up FastEthernet2/0 192.168.3.1 YES manual up up '''#用'''可以匹配大段字符串 ip_address=re.search(r"\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}",ip) print(ip_address.group())

輸出:

192.168.1.1

??這里我們用正則表達式\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3}做為模式來匹配任意IPv4地址,注意我們在分割每段IP地址的‘.’前面加了轉義符號\,如果不加\,寫成\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3}的話,那么將會匹配到’GigabitEthernet1/1’中的’1/1’.
??print (a.group())后可以看到這里我們只匹配到了192.168.1.1這一個IPv4地址,如果想匹配到其他所有的IPv4地址,必須用到grre.findall()。

3.3 re.findall()

??如果字符串中有多個關鍵詞都能被匹配出來,那么可以使用re.findall()。與re.match()和re.search()不一樣的是,re.findall()的返回值是列表,不需要.group()。

import re ip='''R6#sh ip int br Interface IP-Address OK? Method Status Protocol FastEthernet0/0 192.168.1.1 YES manual up up FastEthernet1/0 192.168.2.1 YES manual up up FastEthernet2/0 192.168.3.1 YES manual up up '''#用'''可以匹配大段字符串 ip_address=re.findall(r"\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}",ip) print(type(ip_address)) print(ip_address)

結果:

<class 'list'> ['192.168.1.1', '192.168.2.1', '192.168.3.1']

??這樣就匹配到了4個人ip地址。

3.4 re.sub()

??re.sub()函數用來替換字符串里被匹配到的字符串的內容。

R1#sh ip arp Protocol Address Age (min) Hardware Addr Type Interface Internet 192.168.13.1 - cc01.3ed8.0000 ARPA FastEthernet0/0 Internet 192.168.13.3 13 cc03.1048.0000 ARPA FastEthernet0/0

??以路由器的arp表為例,替換兩個mac地址。

import re mac='''R1#sh ip arp Protocol Address Age (min) Hardware Addr Type Interface Internet 192.168.13.1 - cc01.3ed8.0000 ARPA FastEthernet0/0 Internet 192.168.13.3 13 cc03.1048.0000 ARPA FastEthernet0/0 '''#用'''可以匹配大段字符串 mac_address=re.sub(r"\w{4}\.\w{4}\.\w{4}",'1234.abcd.12ab',mac) print(type(mac_address)) print(mac_address)

結果:

<class 'str'> R1#sh ip arp Protocol Address Age (min) Hardware Addr Type Interface Internet 192.168.13.1 - 1234.abcd.12ab ARPA FastEthernet0/0 Internet 192.168.13.3 13 1234.abcd.12ab ARPA FastEthernet0/0

用1234.abcd.12ab替換了兩個mac地址,默認是匹配的到的都替換。用re.sub()返回值是str,也就是字符串,也不用.goup()

如果只想改變某一個位置的mac地址可以加上參數

import re mac='''R1#sh ip arp Protocol Address Age (min) Hardware Addr Type Interface Internet 192.168.13.1 - cc01.3ed8.0000 ARPA FastEthernet0/0 Internet 192.168.13.3 13 cc03.1048.0000 ARPA FastEthernet0/0 '''#用'''可以匹配大段字符串 mac_address=re.sub(r"\w{4}\.\w{4}\.\w{4}",'1234.abcd.12ab',mac,1) print(type(mac_address)) print(mac_address)

re.sub()里有一個最后一個位置為optional選項,如果是1則只有第一個被匹配到的會被替換,如果是2則是前兩個被匹配到的會被替換。
結果:

<class 'str'> R1#sh ip arp Protocol Address Age (min) Hardware Addr Type Interface Internet 192.168.13.1 - 1234.abcd.12ab ARPA FastEthernet0/0 Internet 192.168.13.3 13 cc03.1048.0000 ARPA FastEthernet0/0

但是如果你想只替換第二個,那么可以用精確匹配。

4 re.match()拓展與練習

??re.match()也可以輸出多個結果,但是本質上也是只匹配了一個字符串內容,但是用.groups()使得用正則表達式匹配出來的內容變成元組,再用元組的索引就可以做到輸出多個結果了。
例1:

import re str1='Port-channel1.189 192.168.189.254 YES CONFIG up 'result=re.match('\s*(.*?)\s+(\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3})\s*(\w+)\s*\w+\s+(\w+)\s*',str1).groups() print(type(result)) print(result)print('-'*80) print('{0:<10}:{1:<}'.format('接口',result[0])) print('{0:<10}:{1:<}'.format('IP地址',result[1])) print('{0:<10}:{1:<}'.format('狀態',result[2]))str2='166 54a2.74f7.0326 DYNAMIC Gi1/0/11'result1=re.match('\s*(\d+)\s*(\w+.\w+.\w+)\s*(\w+)\s*(\w.*)\s*',str2).groups() print(result1) print('-'*80) print('{:<10}:{:<}'.format('vlan id',result1[0])) print('{:<10}:{:<}'.format('mac',result1[1])) print('{:<10}:{:<}'.format('Type',result1[2])) print('{:<10}:{:<}'.format('interface',result1[3]))

輸出:

<class 'tuple'> ('Port-channel1.189', '192.168.189.254', 'YES', 'up') -------------------------------------------------------------------------------- 接口 :Port-channel1.189 IP地址 :192.168.189.254 狀態 :YES ('166', '54a2.74f7.0326', 'DYNAMIC', 'Gi1/0/11') -------------------------------------------------------------------------------- vlan id :166 mac :54a2.74f7.0326 Type :DYNAMIC interface :Gi1/0/11Process finished with exit code 0

例2

import re tr = """TCP Student 192.168.189.167:32806 Teacher 137.78.5.128:65247, idle 0:00:00, bytes 74, flags UIO TCP Student 192.168.189.167:80 Teacher 137.78.5.128:65233, idle 0:00:03, bytes 334516, flags UIO""" str_list = tr.split('\n') #print(str_list )zidian={} for x in str_list:#print('1',x)result1 = re.match('(\s*\w+\s+\w+)\s+(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}).(\d+)\s+(\w+)\s+(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}).(\d+).\s+(\w+\s+)(\d.\d+.\d+.).*\w+\s(\d+).*\w+\s+(\w+)\s*',x).groups()#print('s',result1)key=result1[1],result1[2],result1[4],result1[6]value=result1[-2],result1[-1]zidian[key]=valueprint("打印字典") print(zidian) print("格式化打印輸出")for key in zidian:print('%10s:%-20s|%10s:%-20s|%10s:%-10s|%10s:%-20s|'%('src',key[0],'src_p',key[1],'dst',key[2],'dit_p',key[3]))print('%10s:%-20s|%10s:%-20s'%('bytes',zidian[key][0],'flags', zidian[key][1])) print("=" * 150)

結果:

打印字典 {('192.168.189.167', '32806', '137.78.5.128', 'idle '): ('74', 'UIO'), ('192.168.189.167', '80', '137.78.5.128', 'idle '): ('334516', 'UIO')} 格式化打印輸出src:192.168.189.167 | src_p:32806 | dst:137.78.5.128| dit_p:idle |bytes:74 | flags:UIO src:192.168.189.167 | src_p:80 | dst:137.78.5.128| dit_p:idle |bytes:334516 | flags:UIO ======================================================================================================================================================

總結

以上是生活随笔為你收集整理的网络工程师——正则表达式(模糊匹配)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。