6

Python中使用re.MULTLINE匹配一个字符串的多行

 3 years ago
source link: https://note.qidong.name/2019/09/python-re-multline/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Python中使用re.MULTLINE匹配一个字符串的多行

2019-09-07 17:42:05 +08  字数:785  标签: Python

有时会遇到这种类型的需求:在一个包括换行符的字符串中,匹配行首以某字符(比如+)开头的行数。

当然,这只是一个具体化的问题,但背后有一个通用场景:如何把一个字符串当做多行来处理,并且还比较高效。

一个形如a\nb\n+c\n+d的字符串,要想知道+开头的行数,大概有以下几种做法。

先按行切分为列表

最差版本

>>> s = 'a\nb\n+c\n+d'
>>> lines = s.split('\n')
>>> len([x for x in lines if x.startswith('+')])
2

以上是最直观的版本,也是最差的版本。 它有许多可以优化的细节。

优化分行

lines = s.splitlines()

直接通过\n来分行,容易出问题。 换行符一共有三种:

  1. \n:Unix及其衍生系统,如Linux、FreeBSD、Mac OS X。
  2. \r\n:Dos衍生系统,主要是Windows。
  3. \r:早期Mac OS,以及一些特殊场景。

其中,\r是回车符号,即return,含义是输入位置移动到行首,对应的是早期打字机把滚筒向左移动到行首的操作; \n是换行符,即newline,含义是输入位置移动到下一行。 由此可见,\r\n才是一次完整的换行操作。 而在Unix系统中,省略\r可以减少编码,因为newline的输入位置一定是行首,丢掉了历史包袱,现在更为流行。

但无论如何,鉴于换行符的复杂性,分行操作建议用splitlines来实现。

改len为sum

sum(1 for x in lines if x.startswith('+'))

由于这里只需要个数,而不需要内容,因此可以用sum来实现计算,省略了生成列表的开销。 对迭代器计算次数,这种方法可以通用。

利用re.MULTLINE做多行匹配

上面的方案有个问题,就是一定要把一个字符串先分为多个小字符串列表。 这在超大字符串场景下,会出现显著的性能问题,对内存的无效占用很高。

利用正则表达式的多行匹配可以解决这个问题。

>>> s = 'a\nb\n+c\n+d'
>>> import re
>>> sum(1 for i in re.finditer(r'^\+', s, re.MULTILINE))
2

这里用到了标准库的re模块。 由于re.search只能找一个,re.find返回的是一个列表,因此这里选择了re.finditer,空间占用降低到了极致。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK