Python Cookbook 2字符串和文本

目录

 

2.1 使用多个分隔符分隔字符串

2.2 字符串开头或结尾匹配

2.3 用shell通配符匹配字符串

2.4 字符串匹配和搜索

2.5 字符串搜索并替换

2.6 字符串忽略大小写的搜索替换

2.7 非贪婪匹配(最短模式匹配)

2.8 多行匹配模式

2.9 将Unicode文本标准化

2.10 在正则式中使用Unicode

2.11 删除字符串中不需要的字符

2.12 审查清理文本字符串

2.13 字符串对齐

2.14 合并拼接字符串

2.15 字符串中插入变量

2.16 以指定列宽格式化字符串

2.17 在字符串中处理html和xml

2.18 字符串令牌解析

2.19 实现一个简单的递归下降分析器

2.20 字节字符串上的字符串操作


2.1 使用多个分隔符分隔字符串

str.split(sep=Nonemaxsplit=-1)

返回一个由字符串内单词组成的列表,使用 sep 作为分隔字符串。 如果给出了 maxsplit,则最多进行 maxsplit 次拆分(因此,列表最多会有 maxsplit+1 个元素)。

>>> name = 'gyf,cx,zzz,sss,aaa'
>>> name.split(',')
['gyf', 'cx', 'zzz', 'sss', 'aaa']

str.split() 只适应于非常简单的字符串分割情形,如果是这样的:

>>> line
'asdf fjdk; afed, fjek,asdf, foo'

分隔符有多种,有分号、逗号、空格,并且分隔符后可能还有空格,str.split() 就不适用了。

re.split(patternstringmaxsplit=0flags=0

用 pattern 分开 string 。 如果在 pattern 中捕获到括号,那么所有的组里的文字也会包含在列表里。

>>> from re import split

'''特殊字符[]表示字符集合,这里分隔符在集合中单独列出;*对它前面的正则式匹配0到任意次重复, 尽量多的匹配字符串。 
'''
>>> split(r'[;,\s]\s*',line)
['asdf', 'fjdk', 'afed', 'fjek', 'asdf', 'foo']

可以用括号获取分隔符

'''特殊字符|
'''
>>> split(r'(;|,|\s)\s*',line)
['asdf', ' ', 'fjdk', ';', 'afed', ',', 'fjek', ',', 'asdf', ',', 'foo']

 

2.2 字符串开头或结尾匹配

检查字符串开头或结尾的一个简单方法是使用 str.startswith() 或者是 str.endswith() 方法

str.startswith(prefix[, start[, end]])

如果字符串以指定的 prefix 开始则返回 True,否则返回 False。 prefix 也可以为由多个供查找的前缀构成的元组(list、tuple就需要先转换为元祖)。 如果有可选项 start,将从所指定位置开始检查。 如果有可选项 end,将在所指定位置停止比较。

'''这是一个unittest单元测试文件,这里验证文件名的开头和后缀
'''
>>> file_name = 'test_check_out.py'

>>> file_name.startswith('test_')
True
>>> file_name.endswith('.py')
True

通过 startswith 和 endswith 检查、过滤并收集:

>>> file_names = ['run_all_case.py','test_check_out.py','test_login.py','search.py','unittest']

'''从列表中筛选出unittest单元测试格式的文件
'''
>>> unittest_file = [f for f in file_names if f.startswith('test_') and f.endswith('.py')]
>>> unittest_file
['test_check_out.py', 'test_login.py']

2.3 用shell通配符匹配字符串

该模块提供用于Unix shell风格的通配符,比如 *.py , Dat[0-9]*.csv 等,Shell样式通配符中使用的特殊字符为:

*

匹配一切

?

匹配任何单个字符

[seq]

匹配seq中的任何字符

[!seq]

匹配任何不在seq中的字符

示例: 

>>> from fnmatch import fnmatch
>>> fnmatch('guoyunfei','guo*')
True
>>> fnmatch('search.py','*.py')
True

 在2.2节中我们用了 startswith 和 endswith 来从列表中筛选出unittest单元测试格式的文件,但假如列表中加入这种格式的“joinin_test.py”,就需要 fnmatch 来筛选出了:

>>> file_names
['run_all_case.py', 'test_check_out.py', 'test_login.py', 'search.py', 'unittest']
>>> file_names.append('joinin_test.py')

>>> unittest_file = [f for f in file_names if ( f.startswith('test_') or fnmatch(f,'*_test.*') )and f.endswith('.py')]

>>> unittest_file
['test_check_out.py', 'test_login.py', 'joinin_test.py']

fnmatch() 函数匹配能力介于简单的字符串方法和强大的正则表达式之间。 如果在数据处理操作中只需要简单的通配符就能完成的时候,这通常是一个比较合理的方案。

如果代码需要做文件名的匹配,最好使用 glob 模块。参考5.13小节。

 

2.4 字符串匹配和搜索

re.match(patternstringflags=0

如果 string 开始的0或者多个字符匹配到了正则表达式样式,就返回一个相应的 匹配对象 。 如果没有匹配,就返回 None ;注意它跟零长度匹配是不同的。注意即便是 MULTILINE 多行模式, re.match() 也只匹配字符串的开始位置,而不匹配每行开始。

>>> s = '11/27/2012'
>>> text = 'Today is 11/27/2012. PyCon starts 3/13/2013.'

>>> import re
>>> re.match(r'\d+/\d+/\d+',s)


'''re.match()总是从字符串开始去匹配
'''
>>> print(re.match(r'\d+/\d+/\d+',text))
None


match() 总是从字符串开始去匹配,如果查找字符串任意部分的模式出现位置, 使用 findall() 方法去代替。

re.findall(patternstringflags=0)

对 string 返回一个不重复的 pattern 的匹配列表, string 从左到右进行扫描,匹配按找到的顺序返回。如果样式里存在一到多个组,就返回一个组合列表;就是一个元组的列表(如果样式里有超过一个组合的话)。空匹配也会包含在结果里。

>>> re.findall(r'\d+/\d+/\d+',text)
['11/27/2012', '3/13/2013']

re.finditer(patternstringflags=0)

和 findall 一样,不过返回的是迭代器

 

2.5 字符串搜索并替换

对于简单的字面模式,直接使用 str.replace() 方法即可:

>>> line = 'Extract the contents of each group'
>>> line.replace('contents','title')
'Extract the title of each group'

对于复杂的模式,请使用 re 模块中的 sub() 函数:

re.sub(patternreplstringcount=0flags=0)

返回通过使用 repl 替换在 string 最左边非重叠出现的 pattern 而获得的字符串。 如果样式没有找到,则不加改变地返回 string。 repl 可以是字符串或函数;如为字符串,则其中任何反斜杠转义序列都会被处理。 如果 repl 是一个函数,那它会对每个非重复的 pattern 的情况调用。这个函数只能有一个 匹配对象 参数,并返回一个替换后的字符串。

>>> text = 'Today is 12/04/2019. Want return 10/01/2015.'
>>> import re
>>> re.sub(r'(\d+)/(\d+)/(\d+)',r'\3-\1-\2',text)
'Today is 2019-12-04. Want return 2015-10-01.'

2.6 字符串忽略大小写的搜索替换

示例:

>>> text = 'UPPER PYTHON, lower python, Mixed Python'
>>> import re
>>> re.findall('python',text)
['python']

查找、替换怎么忽略大小写呢?

re.IGNORECASE

进行忽略大小写匹配

>>> re.findall('python',text,flags = re.IGNORECASE)
['PYTHON', 'python', 'Python']
>>> 
>>> re.sub('python','java',text,flags = re.IGNORECASE)
'UPPER java, lower java, Mixed java'

替换中, 要得到“UPPER JAVA, lower java, Mixed Java”,需要有个辅助函数,具体https://python3-cookbook.readthedocs.io/zh_CN/latest/c02/p06_search_replace_case_insensitive.html

2.7 非贪婪匹配(最短模式匹配)

'*''+',和 '?' 修饰符都是 贪婪的;它们在字符串进行尽可能多的匹配。有时候并不需要这种行为。如果正则式 <.*> 希望找到 ' b '.点在默认模式,匹配除了换行的任意字符),它将会匹配整个字符串,而不仅是 ''

*?+???

在修饰符之后添加 ? 将使样式以 非贪婪`方式或者 :dfn:`最小 方式进行匹配; 尽量  的字符将会被匹配。 使用正则式 <.*?> 将会仅仅匹配 ''

>>> books = 'english'

>>> re.findall(r'<.*>',books)
['english']

>>> re.findall(r'<.*?>',books)
['', '']

2.8 多行匹配模式

re.compile() 函数接受一个标志参数叫 re.DOTALL ,它可以让正则表达式中的点(.)匹配包括换行符在内的任意字符。https://python3-cookbook.readthedocs.io/zh_CN/latest/c02/p08_regexp_for_multiline_partterns.html

2.9 将Unicode文本标准化

处理Unicode字符串,需要确保所有字符串在底层有相同的表示,可以使用unicodedata模块先将文本标准化https://docs.python.org/zh-cn/3/library/unicodedata.html?highlight=unicodedata#unicodedata.normalize

2.10 在正则式中使用Unicode

2.11 删除字符串中不需要的字符

怎么去掉文本字符串开头,结尾或者中间不想要的字符(比如空白)?

strip() 方法能用于删除开始或结尾的字符。 lstrip() 和 rstrip() 分别从左和从右执行删除操作。 需要注意的是去除操作不会对字符串的中间的文本产生任何影响。

>>> l = 'gyf _ gyf _gyf'
>>> l.strip('gyf')
' _ gyf _'
>>> l.lstrip('gyf')
' _ gyf _gyf'
>>> l.rstrip('gyf')
'gyf _ gyf _'

去掉文本字符串中间的字符,可以用前面 2.5 的 str.replace() 和 正则表达式的替换 re.sub()

>>> l.replace('gyf','')
' _  _'
>>> import re
>>> re.sub('gyf','',l)
' _  _'

对于更高阶的strip,可能需要使用 translate() 方法。请参阅下一节了解更多关于字符串清理的内容。

2.12 审查清理文本字符串

str.translate(table)

返回原字符串的副本,其中每个字符按给定的转换表进行映射。

>>> map = {ord('\f') : ' ',ord('\t') : ' ',ord('\r') : ' '}
>>> l = 'Python\fis\tawesome\r\n'
>>> l.translate(map)
'Python is awesome \n'

https://python3-cookbook.readthedocs.io/zh_CN/latest/c02/p12_sanitizing_clean_up_text.html

2.13 字符串对齐

对于基本的字符串对齐操作,可以使用字符串的 ljust() , rjust() 和 center() 方法

str.ljust(width[, fillchar])

返回长度为 width 的字符串,原字符串在其中靠左对齐。 使用指定的 fillchar 填充空位 (默认使用 ASCII 空格符)。 如果 width 小于等于 len(s) 则返回原字符串的副本。

>>> title
'Python is awesome!'

>>> title.center(len(title),'_')
'Python is awesome!'

>>> title.center(len(title)+6,'_')
'___Python is awesome!___'

也可以使用 format()

>>> format(title,'_^len(title)+6')
Traceback (most recent call last):
  File "", line 1, in 
    format(title,'_^len(title)+6')
ValueError: Invalid format specifier

>>> format(title,'_^24')
'___Python is awesome!___'

https://python3-cookbook.readthedocs.io/zh_CN/latest/c02/p13_aligning_text_strings.html

 

2.14 合并拼接字符串

加号(+)操作符:

>>> 'a' + 'b'
'ab'

使用加号(+)操作符去连接大量的字符串的时候是非常低效率的, 因为加号连接会引起内存复制以及垃圾回收操作

str.join(iterable)

返回一个由 iterable 中的字符串拼接而成的字符串。 如果 iterable 中存在任何非字符串值包括 bytes 对象则会引发 TypeError。 调用该方法的字符串将作为元素之间的分隔。

>>> items = (i for i in 'guoyunfei')
>>> '!'.join(items)
'g!u!o!y!u!n!f!e!i'

2.15 字符串中插入变量

format()

https://python3-cookbook.readthedocs.io/zh_CN/latest/c02/p15_interpolating_variables_in_strings.html

2.16 以指定列宽格式化字符串

textwrap.fill(textwidth=70**kwargs)

对 text 中的单独段落自动换行,并返回一个包含被自动换行段落的单独字符串。

>>> s = "Look into my eyes, look into my eyes, the eyes, the eyes, the eyes, not around the eyes, don't look around the eyes, look into my eyes, you're under."
>>> import textwrap
>>> textwrap.fill(s,width=70)
"Look into my eyes, look into my eyes, the eyes, the eyes, the eyes,\nnot around the eyes, don't look around the eyes, look into my eyes,\nyou're under."

textwrap 模块对于字符串打印是非常有用的,特别是当你希望输出自动匹配终端大小的时候。 你可以使用 os.get_terminal_size() 方法来获取终端的大小尺寸。

2.17 在字符串中处理html和xml

替换文本字符串中的 ‘<’ 或者 ‘>’ ,使用 html.escape() 函数可以很容易的完成

html.escape(squote=True)

将字符串 s 中的字符``&`` 、 < 和 > 转换为安全的HTML序列。 如果需要在 HTML 中显示可能包含此类字符的文本,请使用此选项。 如果可选的标志 quote 为真值,则字符 (") 和 (') 也被转换;这有助于包含在由引号分隔的 HTML 属性中,如 

>>> s = 'Elements are written as "text".'

>>> import html
>>> print(html.escape(s))
Elements are written as "<tag>text</tag>".

https://python3-cookbook.readthedocs.io/zh_CN/latest/c02/p17_handle_html_xml_in_text.html

2.18 字符串令牌解析

2.19 实现一个简单的递归下降分析器

2.20 字节字符串上的字符串操作

你可能感兴趣的:(#,Python,Cookbook,Python,Cookbook)