在python中如何设计一个正则表达式模式来匹配空白字符

497 阅读3分钟

问题的提出

💬 挑战:如何设计一个正则表达式模式来匹配空白字符,如空位 和表格字符 ,但不匹配换行字符 ?' ' '\t' '\n'

一个例子是用逗号替换一个以空格分隔的文件之间的所有空格(换行符除外),以获得CSV。

方法1:使用字符类

字符类模式[ \t] 匹配一个空位' ' 或一个表格字符'\t' ,但不匹配换行符。如果你想匹配除换行符以外的任意数量的空位,请在模式中附加加号量词,像这样。[ \t]+.

下面是一个例子,你用逗号替换所有分隔的空白(除换行符外),得到CSV格式的输出。

import re

txt = 'a   \t  b        c\nd  e   f'
csv_txt = re.sub('[ \t]+', ',', txt)
print(csv_txt)

输出

a,b,c
d,e,f

为什么模式中的空格是[ \t]

模式中出现空格的原因是为了匹配空位。字符类本质上是一种OR关系,也就是说,字符类中的一项被匹配。对于给定的模式,它要么匹配空位' ' ,要么匹配表格式字符'\t'

方法2:匹配单个不同的空白字符

前面的方法只匹配水平制表符(U+0009)和断裂空间(U+0020)字符。如果你想更精细地控制哪些空白字符需要匹配,哪些不需要,你可以使用下面的基线方法。

以下是Unicode空白字符的列表 [UNICODE_WHITESPACES](https://www.lesinskis.com/python-unicode-whitespace.html)包含了所有你可能想要检查字符串的主要空白变体。你可以使用字符串表达式'[' + ''.join(UNICODE_WHITESPACES) + ']' ,生成一个字符类。

下面是一个变种,它可以在一个给定的文本中找到所有匹配的空白字符。

import re

UNICODE_WHITESPACES = [
    "\u0009", # character tabulation
    "\u000a", # line feed
    "\u000b", # line tabulation
    "\u000c", # form feed
    "\u000d", # carriage return
    "\u0020", # space
    "\u0085", # next line
    "\u00a0", # no-break space
    "\u1680", # ogham space mark
    "\u2000", # en quad
    "\u2001", # em quad
    "\u2002", # en space
    "\u2003", # em space
    "\u2004", # three-per-em space
    "\u2005", # four-per-em space
    "\u2006", # six-per-em space
    "\u2007", # figure space
    "\u2008", # punctuation space
    "\u2009", # thin space
    "\u200A", # hair space
    "\u2028", # line separator
    "\u2029", # paragraph separator
    "\u202f", # narrow no-break space
    "\u205f", # medium mathematical space
    "\u3000", # ideographic space
]

txt = ' \t\n\r'
pattern = '[' + ''.join(UNICODE_WHITESPACES) + ']'
matches = re.findall(pattern, txt)
print(matches)
# [' ', '\t', '\n', '\r']

当然,你可以将其限制为只包含与换行无关的空白字符。

方法3:匹配除换行符以外的各个不同的空白处

下面的代码片段使用了UNICODE_WHITESPACES 常量,但注释了换行的空白,这样与换行有关的字符,如'\n''\r' 就不会再被匹配了!

import re

UNICODE_WHITESPACES = [
    "\u0009", # character tabulation
    # "\u000a", # line feed
    "\u000b", # line tabulation
    "\u000c", # form feed
    # "\u000d", # carriage return
    "\u0020", # space
    # "\u0085", # next line
    "\u00a0", # no-break space
    "\u1680", # ogham space mark
    "\u2000", # en quad
    "\u2001", # em quad
    "\u2002", # en space
    "\u2003", # em space
    "\u2004", # three-per-em space
    "\u2005", # four-per-em space
    "\u2006", # six-per-em space
    "\u2007", # figure space
    "\u2008", # punctuation space
    "\u2009", # thin space
    "\u200A", # hair space
    # "\u2028", # line separator
    # "\u2029", # paragraph separator
    "\u202f", # narrow no-break space
    "\u205f", # medium mathematical space
    "\u3000", # ideographic space
]

txt = ' \t\n\r'
pattern = '[' + ''.join(UNICODE_WHITESPACES) + ']'
matches = re.findall(pattern, txt)
print(matches)
# [' ', '\t']

当然,你可以根据自己的应用需要,注释出你不想匹配的个别空白Unicode字符。