match vs findall vs finditer
背景需求
希望从自己的Crifan的电子书的使用说明的README.md中提取相关book的信息,比如url,name,title等。
re.search处理单行,返回匹配对象Match Object
对于普通的,单行字符串:
* [科学上网](https://book.crifan.com/books/scientific_network_summary/website)
一般用re.search
代码去查找:
foundBook = re.search("https?://book\.crifan\.com/books/(?P<bookName>\w+)/website", singleLineMdStr)
print("foundBook=%s" % foundBook)
代码解析:
https?
=https
加上问号?
- 表示:
http
后面,可能有s
,也可能没有s
- 用于匹配:
http://xxx
和https://xxx
的链接
- 表示:
(?P<bookName>\w+)
- 典型的
named group
=命名的组
的写法- 语法:
(?P<yourGroupName>match_pattern)
- 此处
yourGroupName
=bookName
- 用于:若匹配到,后续可通过
foundBook.group("bookName")
提取这部分的值
- 用于:若匹配到,后续可通过
match_pattern
=\w+
- 表示:至少1个(1个或更多个)的大小写字母或下划线
- 用于匹配:此处的
scientific_network_summary
- 此处
- 语法:
- 典型的
得到的是一个Match Object
foundBook=<re.Match object; span=(9, 73), match='https://book.crifan.com/books/scientific_network_>
后来典型写法就是提取出所需的部分,比如
if foundBook:
bookName = foundBook.group("bookName")
print("bookName=%s" % bookName)
得到book的name:
bookName=scientific_network_summary
re.findall处理多行,返回整个匹配字符串或group部分的字符串
对于多行字符串:
* 推荐工具
* [科学上网](https://book.crifan.com/books/scientific_network_summary/website)
* 编辑器和IDE
* [总结](https://book.crifan.com/books/editor_ide_summary/website/)
* 好用工具
* [VSCode](http://book.crifan.com/books/best_editor_vscode/website)
返回单条全部内容
如果只是想要获取所有的book的url,则可以用re.findall
,且不要加组group:
allBookUrlList = re.findall("https?://book\.crifan\.com/books/\w+/website", multipleLineDdStr)
print("allBookUrlList=%s" % allBookUrlList)
输出:
allBookUrlList=['https://book.crifan.com/books/scientific_network_summary/website', 'https://book.crifan.com/books/editor_ide_summary/website', 'http://book.crifan.com/books/best_editor_vscode/website']
返回单条中的部分内容=组的内容
如果只想要获取,每条匹配的内容中的其中一部分,即其中某个或某几个group组的内容,则加上group:
allBookNameList = re.findall("https?://book\.crifan\.com/books/(?P<bookName>\w+)/website", multipleLineDdStr, re.S)
print("allBookNameList=%s" % allBookNameList)
输出:
# allBookNameList=['scientific_network_summary', 'editor_ide_summary', 'best_editor_vscode']
re.findall的两种用法对比
- re.findall的两种用法对比
- 规则:
"https?://book\.crifan\.com/books/\w+/website"
- 不带group组
- 返回:单条匹配的所有内容,即whole single match string
- 举例:
'https://book.crifan.com/books/scientific_network_summary/website'
- 举例:
- 返回:单条匹配的所有内容,即whole single match string
- 不带group组
- 规则:
https?://book\.crifan\.com/books/(?P<bookName>\w+)/website
- 带group组
- 返回:单条匹配到的所有内容中的其中一部分,即group组的部分,matched group string
- 举例:
'scientific_network_summary'
- 举例:
- 返回:单条匹配到的所有内容中的其中一部分,即group组的部分,matched group string
- 带group组
- 规则:
re.finditer处理多行,返回多个(re.search所返回的)匹配对象
而对于re.finditer,可以视为 = re.findall
+ re.search
即:就像re.findall
一样,返回多个值,但是每个值,不是re.findall
直接返回(匹配到的)字符串,而是(re.search所返回的)匹配的对象Match Object
下面用具体例子来解释:
re.finditer
内部就像re.findall
和之前一样,想要返回所有的book的url,则可以写成:
allBookUrlMatchObjIterator = re.finditer("https?://book\.crifan\.com/books/\w+/website", multipleLineDdStr)
print("allBookUrlMatchObjIterator=%s" % allBookUrlMatchObjIterator)
此处注意返回的是iterator
:
# allBookUrlMatchObjIterator=<callable_iterator object at 0x11063f160>
可以将其转换为list
:
allBookUrlMatchObjList = list(allBookUrlMatchObjIterator)
print("allBookUrlMatchObjList=%s" % allBookUrlMatchObjList)
得到了Match Object
的list
:
# allBookUrlMatchObjList=[<re.Match object; span=(19, 83), match='https://book.crifan.com/books/scientific_network_>, <re.Match object; span=(108, 164), match='https://book.crifan.com/books/editor_ide_summary/>, <re.Match object; span=(195, 250), match='http://book.crifan.com/books/best_editor_vscode/w>]
接着就可以对list去枚举处理了:
for curIdx, eachMatchObj in enumerate(allBookUrlMatchObjList):
singleMatchWholeStr = eachMatchObj.group(0)
print("[%d] singleMatchWholeStr=%s" % (curIdx, singleMatchWholeStr))
从每个匹配的对象获取所需要的完整的url值:
# [0] singleMatchWholeStr=https://book.crifan.com/books/scientific_network_summary/website
# [1] singleMatchWholeStr=https://book.crifan.com/books/editor_ide_summary/website
# [2] singleMatchWholeStr=http://book.crifan.com/books/best_editor_vscode/website
re.finditer
内部就像re.search
而如果想要一次性的匹配得到多个匹配对象Match Object
,且每个都可以提取对应的group组的值,则可以给规则中加上group组:
allBookNameMatchObjIterator = re.finditer("https?://book\.crifan\.com/books/(?P<bookName>\w+)/website", multipleLineDdStr)
print("allBookNameMatchObjIterator=%s" % allBookNameMatchObjIterator)
同理先是得到iterator
:
# allBookNameMatchObjIterator=<callable_iterator object at 0x10e9a9fd0>
再转换为list
:
allBookNameMatchObjList = list(allBookNameMatchObjIterator)
print("allBookNameMatchObjList=%s" % allBookNameMatchObjList)
即多个匹配对象:
# allBookNameMatchObjList=[<re.Match object; span=(19, 83), match='https://book.crifan.com/books/scientific_network_>, <re.Match object; span=(108, 164), match='https://book.crifan.com/books/editor_ide_summary/>, <re.Match object; span=(195, 250), match='http://book.crifan.com/books/best_editor_vscode/w>]
然后继续针对每个匹配对象去处理:
for curIdx, eachMatchObj in enumerate(allBookNameMatchObjList):
singleMatchWholeStr = eachMatchObj.group(0)
singleMatchBookName = eachMatchObj.group("bookName")
print("[%d] singleMatchWholeStr=%s, singleMatchBookName=%s" % (curIdx, singleMatchWholeStr, singleMatchBookName))
即可,既能获取到 单个匹配的完整字符串,又能获取到 每个匹配的全部字符串中特定的组的内容了:
# [0] singleMatchWholeStr=https://book.crifan.com/books/scientific_network_summary/website, singleMatchBookName=scientific_network_summary
# [1] singleMatchWholeStr=https://book.crifan.com/books/editor_ide_summary/website, singleMatchBookName=editor_ide_summary
# [2] singleMatchWholeStr=http://book.crifan.com/books/best_editor_vscode/website, singleMatchBookName=best_editor_vscode
附录:
完整代码详见: