问题的提出
挑战:如何设计一个正则表达式模式来匹配空白字符,如空位 和表格字符 ,但不匹配换行字符 ?
' ' '\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字符。