惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

C
CXSECURITY Database RSS Feed - CXSecurity.com
Help Net Security
Help Net Security
P
Privacy International News Feed
S
Securelist
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
T
Tor Project blog
AWS News Blog
AWS News Blog
K
Kaspersky official blog
A
Arctic Wolf
Latest news
Latest news
T
Threat Research - Cisco Blogs
L
LINUX DO - 最新话题
P
Privacy & Cybersecurity Law Blog
Security Archives - TechRepublic
Security Archives - TechRepublic
Google DeepMind News
Google DeepMind News
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
月光博客
月光博客
N
News and Events Feed by Topic
Jina AI
Jina AI
博客园 - 司徒正美
WordPress大学
WordPress大学
罗磊的独立博客
雷峰网
雷峰网
AI
AI
Hugging Face - Blog
Hugging Face - Blog
D
Darknet – Hacking Tools, Hacker News & Cyber Security
S
Security @ Cisco Blogs
博客园 - 三生石上(FineUI控件)
H
Heimdal Security Blog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
酷 壳 – CoolShell
酷 壳 – CoolShell
C
Cisco Blogs
博客园 - 【当耐特】
The Hacker News
The Hacker News
有赞技术团队
有赞技术团队
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
www.infosecurity-magazine.com
www.infosecurity-magazine.com
Schneier on Security
Schneier on Security
博客园 - Franky
S
SegmentFault 最新的问题
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Cloudbric
Cloudbric
爱范儿
爱范儿
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
S
Secure Thoughts
Last Week in AI
Last Week in AI
Application and Cybersecurity Blog
Application and Cybersecurity Blog
Know Your Adversary
Know Your Adversary
Google DeepMind News
Google DeepMind News

晚花行乐

马克卡尼在2026年达沃斯论坛上的讲话(阅读材料) | 晚花行乐 鸡娃如何用力才是恰到好处 | 晚花行乐 读万卷书,行万里路的辩证关系 | 晚花行乐 反对培训机构掐尖招生 | 晚花行乐 小泽和建国会谈最后10分钟全文(阅读材料) | 晚花行乐 来看看 DeepSeek 怎么鸡娃 | 晚花行乐 谈谈基本功 | 晚花行乐 惠普 ProDesk SFF PC 各系列参数对比 | 晚花行乐 解决瘦客户机上安装 Debian 12 启动失败问题 | 晚花行乐 意拾喻言:老外写的文言文 | 晚花行乐 笠翁对韵中的典故(十三元) | 晚花行乐 谈谈中考取消四小门 | 晚花行乐 亚马逊云科技产品免费试用攻略(3) - 对象存储服务 | 晚花行乐 在 Windows 10 LTSC 版本上安装 WSL2 | 晚花行乐 Debian 12 的常用配置项 | 晚花行乐 在 Debian 12 上安装 Nvidia 显卡驱动程序 | 晚花行乐 解决 Debian 12 关机失败问题 | 晚花行乐 解决 VS Code 自动更新版本后卡在连接界面 | 晚花行乐 观看巴黎奥运会有感 | 晚花行乐 在 Windows10 上安装惠普旧打印机驱动程序 | 晚花行乐 欢迎关注公众号:晚花行乐 | 晚花行乐 如何编写拼写检查器 | 晚花行乐 亚马逊云科技产品免费试用攻略(2) - 云服务器 | 晚花行乐 Pandas 中 axis 参数的理解(附实例) | 晚花行乐 我打算命个名,叫什么什么 Manager | 晚花行乐 上海武康路历史建筑一览 | 晚花行乐 Python 实现简单的数学表达式解析并处理 | 晚花行乐 观看马拉松的感悟 | 晚花行乐 Python 保存 Cookies 到文件并再次读取 | 晚花行乐 如何为 Hugo 静态网站添加评论功能 | 晚花行乐 Linux 共享打印服务 CUPS | 晚花行乐 如何为 Hugo 静态网站添加搜索功能 | 晚花行乐 解决 CSV 文件的第一列不能解析 | 晚花行乐 亚马逊云科技产品免费试用攻略(1) - 注册账户 | 晚花行乐 第二幕 Atma 的闲聊 | 晚花行乐 第二幕野蛮人的语音 | 晚花行乐 古入声和普通话平声对照 | 晚花行乐 第一幕的背景音乐 | 晚花行乐 第二幕亚马逊的语音 | 晚花行乐 第一幕的亚马逊的语音 | 晚花行乐 第一幕的野蛮人的语音 | 晚花行乐 MacOS 的彩蛋:Here's to the crazy ones | 晚花行乐 笠翁对韵的基本知识 | 晚花行乐 笠翁对韵中的典故(十二文) | 晚花行乐 笠翁对韵中的典故(十一真) | 晚花行乐 笠翁对韵中的典故(十灰) | 晚花行乐 杭州景点的楹联 | 晚花行乐 adb keycode 大全 | 晚花行乐 Scikit-learn 学习笔记(0)名词术语 | 晚花行乐 Scikit-learn 学习笔记(3)监督学习的例子 | 晚花行乐 SQLite 文档的学习笔记(1)长期支持计划 | 晚花行乐 SQLite 文档的学习笔记(2)测试方法 | 晚花行乐 笠翁对韵中的典故(九佳) | 晚花行乐 Ansible 如何检查一个程序的版本 | 晚花行乐 Ansible 如何检查一个文件夹是否存在 | 晚花行乐 pip 配置文件详解 | 晚花行乐 Ansible 如何检查一个URL是否正常 | 晚花行乐 Ansible 如何修改 iptables 规则 | 晚花行乐 Ansible 指定 playbook 运行的主机 | 晚花行乐 Ansible 如何清空文件夹 | 晚花行乐 Ansible 如何在本机执行命令 | 晚花行乐 笠翁对韵中的典故(八齐) | 晚花行乐 Python 中 Defaultdict 的理解 | 晚花行乐 《伊索寓言》电子书 | 晚花行乐 菲伯尔钢琴伴奏:第二册 | 晚花行乐 Python 的 Keyword-Only Arguments 理解 | 晚花行乐 Python 的 函数参数处理机制 | 晚花行乐 瓦瑞夫在第一幕的闲聊 | 晚花行乐 瓦瑞夫在第一幕的任务提示 | 晚花行乐 第一幕的女巫语音 | 晚花行乐 《Fluent Python》 读书笔记:文本和字节序列 | 晚花行乐 第一幕的罗格语音 | 晚花行乐 第一幕的圣骑士语音 | 晚花行乐 第一幕的男巫语音 | 晚花行乐 第一幕的旁白 | 晚花行乐 第一幕的恶魔 | 晚花行乐 Python 中 Element Tree 的理解 | 晚花行乐 笠翁对韵中的典故(七虞) | 晚花行乐 笠翁对韵中的典故(五微) | 晚花行乐 笠翁对韵中的典故(六鱼) | 晚花行乐 笠翁对韵中的典故(一东) | 晚花行乐 笠翁对韵中的典故(二冬) | 晚花行乐 笠翁对韵中的典故(三江) | 晚花行乐 笠翁对韵中的典故(四支) | 晚花行乐 姜太公钓鱼 | 晚花行乐 武王建立周朝 | 晚花行乐 大禹治水 | 晚花行乐 尧舜让位 | 晚花行乐 黄帝战蚩尤 | 晚花行乐 上下五千年-精简版 | 晚花行乐 成功修复鼠标按键 | 晚花行乐 横向的Word文档怎么加页眉页脚 | 晚花行乐 商标通用化的故事:商标代替商品名 | 晚花行乐 搜索空文件夹的批处理程序 | 晚花行乐 Sn0wbreeze不能运行? | 晚花行乐 天线的驻波比 | 晚花行乐 天线参数:增益Gain | 晚花行乐 天线参数:方向图Radiation pattern | 晚花行乐 本拉登别墅的Google Earth坐标 | 晚花行乐 宜家帕克斯(PAX)衣柜的拼装过程 | 晚花行乐
Python 正则表达式里的单行s和多行m模式 | 晚花行乐
2014-08-18 · via 晚花行乐

Python 的 re 模块内置函数几乎都有一个 flags 参数,规定了正则匹配时的各种策略模式,其中有两个模式:单行(re.DOTALL, 或者re.S)和多行(re.MULTILINE, 或者re.M)模式。本文简单介绍下这两种模式的用法和使用场合。

TL;DR

太长不看版:

  • 单行模式和多行模式,都增强了对多行文本的解析能力。\
  • 单行模式突破换行符 \n 的阻碍,将匹配视野扩大到整个字符串\
  • 多行模式实现换行符 \n 的分隔,将匹配视野缩小到一行之内,并且按行分别匹配。

文件的保存形式:字节流

首先我们需要清楚,你看到的多行文本在视觉上是二维的,有行和列的表达:比如我们新建一个文件,名字叫 a.txt ,内容是:

cat
dog

用文本编辑器打开,看到的是两行文字,每行有三个字符,所以这是个二维的表示。

但是,文件的保存形式只能是一维的字节流,之所以能让编辑器表示为二维形状,都是因为字节流中包含了换行符。

我们用 xxd 命令看下这个 a.txt 文件的二进制表达:

$ xxd -b a.txt
0000000: 01100011 01100001 01110100 00001010 01100100 01101111  cat.do
0000006: 01100111 00001010                                      g.

这就是文件 a.txt 真实保存的形式,其中 00001010 就是换行符。

为了能看得更清楚,用16进制查看文件:

$ xxd a
0000000: 6361 740a 646f 670a                      cat.dog.

Linux环境下, 0a 就是换行符,在编程语言里用 \n 表示,不同操作系统下的换行符有少许不同,见这篇文章 Python 换行符和多行模式

结论:一段多行文本,尽管在文本编辑器中显示为二维的形状,但是在正则表达式解析器看来,文件是一维的字符串。在碰到包含换行符的字符串时,有多种匹配模式,分别能得到不同的结果。

在线测试工具

首先我们使用一款在线工具以得到感性认识。(建议在 PC 端 Chrome 浏览器中使用,其他浏览器效果不能保证)。

复制下面一段多行文字:

空山新雨后,
天气晚来秋。
明月松间照,
清泉石上流。

并粘贴到下方文本框中:

在普通匹配模式 ".+" 下,得到如下的结果,匹配到第一行末尾即停止。

空山新雨后,

单行匹配模式 ".+", re.DOTALL 下,得到如下结果,可见匹配出了包括换行符在内的所有字符

空山新雨后,\n天气晚来秋。\n明月松间照,\n清泉石上流。

在多行匹配模式 "^.+$" re.MULTILINE 下,得到如下结果,可见匹配结果本身也是多行:

空山新雨后,
天气晚来秋。
明月松间照,
清泉石上流。

普通模式

正则表达式(Python2Python3)里, 点号(.)能匹配除换行符以外的所有字符。文档中的原话是:

In the default mode, this matches any character except a newline.

当用 .* 匹配到换行符的前面时,匹配即停止。例如下面这样的字符串:

This is the first line.
This is the second line.
This is the third line.

直接使用 .* 匹配,匹配过程如下面图所示(点击左上角的"点击播放"):

执行代码的例子,如下面的执行过程。从匹配结果可以看出来,仅有第一行出现在结果里,而且不包含换行符。

>>> a = 'This is the first line.\nThis is the second line.\nThis is the third line.'
>>> print a
This is the first line.
This is the second line.
This is the third line.
>>> import re
>>> p = re.match(r'This.*line\.' ,a) 
>>> p.group(0)
'This is the first line.'
>>>

结论:

普通模式下,点号(.)不能匹配换行符,匹配动作遇到换行符即停止。

单行模式 re.DOTALL

在上面的例子里,即使是默认的贪婪(greedy)模式,仍然在第一行的结尾初停止了匹配。如果想完整匹配出字符串,就需要进入 单行模式Python 文档中这么描述:

If the DOTALL flag has been specified, this matches any character including a newline.

在单行模式下,匹配的行为模式如下图,点击左上角的"点击播放"查看匹配过程:

从上面的动图里可以看出,当使用 re.DOTALL 时,点号将同时匹配换行符,实现了跨行匹配。代码的执行过程如下,从下面的记过可以看出,匹配结果里包含了换行符 \n 和 全部的三行。

>>> q = re.match(r'This.*line\.', a, flags=re.DOTALL)
>>> q.group(0)
'This is the first line.\nThis is the second line.\nThis is the third line.'

结论:

单行模式下,点号(.)也能匹配换行符,多行文本被当作一行匹配。

这里引申出比较奇怪的结论就是:为了能匹配出多行文本,你应该使用单行模式。

多行模式 re.MULTILINE

有时候我们想找出一篇文章里符合特定条件一共有几行。比如在下面的例子里,我们希望找出 所有 以 This 开头,以 line 结尾的行。

>>> a = 'This is the first line.\nThis is the second line.\nThis is the third line.'
>>> print a
This is the first line.
This is the second line.
This is the third line.
>>> import re
>>> re.findall(r'^This.*line\.$', a)
[]
>>>

匹配结果为空的原因是:从 上一节 我们知道,点号不匹配换行符,最多只能匹配到第一个 line,但是第一个 line 后面并没有行尾符 $,假如我们改用 单行模式

>>> re.findall(r'^This.*line\.$', a, flags=re.DOTALL)
['This is the first line.\nThis is the second line.\nThis is the third line.']
>>>

匹配模式中的 line 就匹配到了第三个line,结果就是匹配出了整个字符串,但这并不是我们想要的, 因为原字符串的三行都满足匹配条件,我们希望有三条结果。

再用问号 ? 切换成非贪婪模式试试:

>>> re.findall(r'^This.*?line\.$', a, flags=re.DOTALL)
['This is the first line.\nThis is the second line.\nThis is the third line.']
>>> 

仍然是整个字符串

真正的原因是因为正常情况下,行首符 ^ 和行尾符 $ 仅仅匹配整个字符串的起始和结尾。Python 文档中这么描述:

By default, ‘^’ matches only at the beginning of the string, and ‘$’ only at the end of the string and immediately before the newline (if any) at the end of the string.

为了扩大 ^$ 的匹配范围,引入了多行模式。在这种模式下:

  • 将换行符 '\n' 后面的位置也看作行首,可以用 ^ 匹配
  • 将换行符 '\n' 前面的位置也看作行尾,可以用 $ 匹配

点击下图左上角的"点击播放",观看多行模式的匹配过程:

Python 文档中这么描述:

When specified, the pattern character ‘^’ matches at the beginning of the string and at the beginning of each line (immediately following each newline); and the pattern character ‘$’ matches at the end of the string and at the end of each line (immediately preceding each newline).

再回到前面的例子中,使用多行模式得到的结果如下:

>>> re.findall(r'^This.*line\.$', a, flags=re.MULTILINE)
['This is the first line.', 'This is the second line.', 'This is the third line.']

结论:

多行模式改变了^和 $ 符号的匹配策略,当字符串中间有 换行符 \n 时,将字符串当作独立的多行对待

当需要在一个文本文件里跨行匹配时,单行和多行模式尤其有用。

二者不冲突

单行模式和多行模式,从名字上看是互斥的,但是实际上,两者可以共存。因为它们二者分别扩展不同的匹配符:点号 .^$

各位读后有什么想法,请在下方留言吧!如果对本文有疑问或者寻求合作,欢迎 联系邮箱邮箱已到剪贴板

精彩评论