正則表達式(Regular expression)是組成搜索模式的一組字符序列,是記錄文本規則的代碼,用來檢查文本中是否包含指定模式的字符串,通過定義一個規則來匹配字符串。正則表達式廣泛應用於在字符串查找和處理中,大多文本編輯器基本都支持正則表達式查找。本文將簡要介紹正則表達式語法,然后介紹Python語言中正則表達式使用方法。
正則表達式
Unix之父Ken Tompson將正則表達式引入Unix,后面發展成了grep(Global Regular Expression Print)命令,由於grep不支持+
、|
與?
,且分組比較麻煩,AT&T的Alfred Aho開發了egrep命令。隨着Unix的版本不斷演化,Unix中的程序(比如Linux三劍客中的awk、sed)所支持的正則表達式有差異,比較混亂。在1986年制定了POSIX(Portable Operating System Interface)標准,其中統一了正則表達式的語法。
POSIX標准把正則表達式分為兩種:BRE(Basic Regular Expressions)和ERE(Extended Regular Expressions )。BRE就是unix系統使用的grep命令,ERE對應egrep命令,是BRE的擴展。而linux系統使用的是GNU標准,linux發行版集成了GNU(Gnu’s Not Unix)套件,GNU在實現了POXIS標准的同時,做了一定的擴展。也包括GNU Basic Regular Expressions 和GNU Extends Regular Expressions。
正則表達式除了POSIX標准之外還有一個Perl分支,Perl與sed和awk兼容,后來演化成為PCRE(Perl Compatible Regular Expressions),是一個用C語言編寫的正則表達式函數庫,功能很強大,性能比POSIX正則表達式好。PCRE被引入了其他語言中,比如PHP, Tcl, Python, Ruby, C++, Java, R語言等等。
普通正則
代碼 | 說明 |
---|---|
. | 匹配除換行符以外的任意字符 |
\w | 匹配字母或數字或下划線或漢字 |
\s | 匹配任意的空白符 |
\d | 匹配數字 |
\b | 匹配單詞的開始或結束 |
^ | 匹配字符串的開始 |
$ | 匹配字符串的結束 |
* | 重復零次或更多次 |
擴展正則
擴展正則:grep加 -E
參數
- grep -E ' 404 | 500' nginx.log
代碼/語法 | 說明 |
---|---|
+ | 重復一次或更多次 |
? | 重復零次或一次 |
{n} | 重復n次 |
{n,} | 重復n次或更多次 |
{n,m} | 重復n到m次 |
| | 表示或 |
零寬斷言
語法 | 說明 |
---|---|
(?=exp) | 匹配exp前面的位置 |
(?<=exp) | 匹配exp后面的位置 |
(?!exp) | 匹配后面不是exp的位置 |
(?<!exp) | 匹配前面不是exp的位置 |
正則表達式實例
正則表達式在線測試工具:
測試文本test.txt
$ cat test.txt
abc
bac
123456
bc
test123
12345678901234
023-12345678
123
GET 1
GET123
GET
test123test
1. 匹配以字母a開頭的單詞
$ grep '\ba\w*\b' test.txt
abc
2. 匹配剛好6個字符的單詞
$ grep -E '\b\w{6}\b' test.txt
123456
GET123
3. 匹配1個或更多連續的數字
$ grep -Po '\d+' test.txt
123456
123
12345678901234
023
12345678
123
1
123
123
4. 5位到12位QQ號
$ grep -P '\d{5,12}' test.txt
123456
12345678901234
023-12345678
$ grep -P '^\d{5,12}$' test.txt
123456
5. 匹配電話號碼
$ grep -P '0\d{2}-\d{8}' test.txt
023-12345678
6. 只匹配3位數字
$ grep -P '^\d{3}$' test.txt
123
7. 查找單詞‘GET’
$ grep '\bGET\b' test.txt
GET 1
GET
$ grep '^GET$' test.txt
GET
8. 匹配兩個字符之間的內容
$ grep -Eo "test(.+?)test" test.txt
test123test
$ grep -Po "(?<=test).*?(?=test)" test.txt
123
9. .*
和.+
的使用方法
$ text1="fn()"
$ text2="fn(6)"
$ echo $text1 | grep "fn\(.*\)"
fn()
$ echo $text2 | grep "fn\(.*\)"
fn(6)
$ echo $text1 | grep -E "fn\(.+\)"
$ echo $text2 | grep -E "fn\(.+\)"
fn(6)
Python正則表達式
Python有一個內置正則表達式模塊 re
,可以使用它來進行字符串操作:
import re
re
模塊提供了以下4種方法:
- findall:返回所有匹配項
- search:如果匹配到目標字符,返回一個匹配對象,用於判斷是否存在目標字符串
- split:分割
- sub:替換
匹配數字、字母
text = '1&\nbsp;hour(s) 2&\nbsp;min 25&\nbsp;s'
re.findall(r'\d+',text) # 匹配時間(數字)
re.findall(r'\d+|(?<=;)\w+',text) # 匹配時間和單位
output:
['1', '2', '25']
['1', 'hour', '2', 'min', '25', 's']
re.findall(r'\d{2}+',text) # 匹配2位數字
查找替換兩個字符串之間內容
替換字符target_text
:
xpath_path = '//*[contains(text(),"target_text")]/../td[5]/span' # xpath路徑
repl = "需要替換成的字符串"
re.sub(r"(?<=\").*?(?=\")", repl, xpath_path) # 替換要查找的文本
output:
'//*[contains(text(),"需要替換成的字符串")]/../td[5]/span'
添加千位分割符
number = '12345678'
re.sub(r"\B(?=(?:\d{3})+(?!\d))", ",",number) # 替換要查找的文本
re.sub(r"\B(?:(?:\d{3})+(?!\d))", ",",number)
output:
'12,345,678'
'12,'
(?:\d{3})+(?!\d)
:
- 查找3n(數字) + 非數字 組合
(?:exp)
:
- 匹配exp,不捕獲匹配的文本(非獲取匹配),也不給此分組分配組號,當執行了第一次匹配時,匹配到了行尾,直接將345678替換成了“,”。
參考文檔
- 正則表達式30分鍾入門教程:https://deerchao.cn/tutorials/regex/regex.htm
- github項目learn-regex:https://github.com/ziishaned/learn-regex
- https://www.w3schools.com/python/python_regex.asp
歡迎關注公眾號:「測試開發小記」及時接收最新技術文章!