python 字符串探讨

     本文内容基于python3

      几乎所有有用的程序都会涉及到某些文本处理,不管是解析数据还是产生输出。字符串的学习是重点中的重点,这一节将重点关注文本的操作处理,比如提取字符串,搜索,替换以及解析等。大部分的问题都能简单的调用字符串的内建方法完成。但是,一些更为复杂的操作可能需要正则表达式或者强大的解析器来实现。

在python中,一切事物都是对象!

因此str是类,int是类,dict、list、tuple等等都是类,但是str却不能直接使用,因为它是抽象的表示了字符串这一类事物,并不能满足表示某个特定字符串的需求,我们必须要str1 = ''初始化一个对象,这时的str1具有str的属性,可以使用str中的方法。

字符串声明:

从字符串类中实例化出的对象

>>> str1 = 'jdq'                                     
>>> str2 = str('jdq')

>>> type(str2)
<class 'str'>

查看类的所有方法:dir(类名)如下,就打印出了所有的类成员。

类成员分为:字段,属性,方法

1 >>> dir(str)
2 ['__add__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__gt__', '__hash__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__mod__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmod__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'capitalize', 'casefold', 'center', 'count', 'encode', 'endswith', 'expandtabs', 'find', 'format', 'format_map', 'index', 'isalnum', 'isalpha', 'isdecimal', 'isdigit', 'isidentifier', 'islower', 'isnumeric', 'isprintable', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'maketrans', 'partition', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill']
  1 class str(basestring):
  2     """
  3     str(object='') -> string
  4     
  5     Return a nice string representation of the object.
  6     If the argument is a string, the return value is the same object.
  7     """
  8     def capitalize(self):  
  9         """ 首字母变大写 """
 10         """
 11         S.capitalize() -> string
 12         
 13         Return a copy of the string S with only its first character
 14         capitalized.
 15         """
 16         return ""
 17 
 18     def center(self, width, fillchar=None):  
 19         """ 内容居中,width:总长度;fillchar:空白处填充内容,默认无 """
 20         """
 21         S.center(width[, fillchar]) -> string
 22         
 23         Return S centered in a string of length width. Padding is
 24         done using the specified fill character (default is a space)
 25         """
 26         return ""
 27 
 28     def count(self, sub, start=None, end=None):  
 29         """ 子序列个数 """
 30         """
 31         S.count(sub[, start[, end]]) -> int
 32         
 33         Return the number of non-overlapping occurrences of substring sub in
 34         string S[start:end].  Optional arguments start and end are interpreted
 35         as in slice notation.
 36         """
 37         return 0
 38 
 39     def decode(self, encoding=None, errors=None):  
 40         """ 解码 """
 41         """
 42         S.decode([encoding[,errors]]) -> object
 43         
 44         Decodes S using the codec registered for encoding. encoding defaults
 45         to the default encoding. errors may be given to set a different error
 46         handling scheme. Default is 'strict' meaning that encoding errors raise
 47         a UnicodeDecodeError. Other possible values are 'ignore' and 'replace'
 48         as well as any other name registered with codecs.register_error that is
 49         able to handle UnicodeDecodeErrors.
 50         """
 51         return object()
 52 
 53     def encode(self, encoding=None, errors=None):  
 54         """ 编码,针对unicode """
 55         """
 56         S.encode([encoding[,errors]]) -> object
 57         
 58         Encodes S using the codec registered for encoding. encoding defaults
 59         to the default encoding. errors may be given to set a different error
 60         handling scheme. Default is 'strict' meaning that encoding errors raise
 61         a UnicodeEncodeError. Other possible values are 'ignore', 'replace' and
 62         'xmlcharrefreplace' as well as any other name registered with
 63         codecs.register_error that is able to handle UnicodeEncodeErrors.
 64         """
 65         return object()
 66 
 67     def endswith(self, suffix, start=None, end=None):  
 68         """ 是否以 xxx 结束 """
 69         """
 70         S.endswith(suffix[, start[, end]]) -> bool
 71         
 72         Return True if S ends with the specified suffix, False otherwise.
 73         With optional start, test S beginning at that position.
 74         With optional end, stop comparing S at that position.
 75         suffix can also be a tuple of strings to try.
 76         """
 77         return False
 78 
 79     def expandtabs(self, tabsize=None):  
 80         """ 将tab转换成空格,默认一个tab转换成8个空格 """
 81         """
 82         S.expandtabs([tabsize]) -> string
 83         
 84         Return a copy of S where all tab characters are expanded using spaces.
 85         If tabsize is not given, a tab size of 8 characters is assumed.
 86         """
 87         return ""
 88 
 89     def find(self, sub, start=None, end=None):  
 90         """ 寻找子序列位置,如果没找到,返回 -1 """
 91         """
 92         S.find(sub [,start [,end]]) -> int
 93         
 94         Return the lowest index in S where substring sub is found,
 95         such that sub is contained within S[start:end].  Optional
 96         arguments start and end are interpreted as in slice notation.
 97         
 98         Return -1 on failure.
 99         """
100         return 0
101 
102     def format(*args, **kwargs): # known special case of str.format
103         """ 字符串格式化,动态参数,将函数式编程时细说 """
104         """
105         S.format(*args, **kwargs) -> string
106         
107         Return a formatted version of S, using substitutions from args and kwargs.
108         The substitutions are identified by braces ('{' and '}').
109         """
110         pass
111 
112     def index(self, sub, start=None, end=None):  
113         """ 子序列位置,如果没找到,报错 """
114         S.index(sub [,start [,end]]) -> int
115         
116         Like S.find() but raise ValueError when the substring is not found.
117         """
118         return 0
119 
120     def isalnum(self):  
121         """ 是否是字母和数字 """
122         """
123         S.isalnum() -> bool
124         
125         Return True if all characters in S are alphanumeric
126         and there is at least one character in S, False otherwise.
127         """
128         return False
129 
130     def isalpha(self):  
131         """ 是否是字母 """
132         """
133         S.isalpha() -> bool
134         
135         Return True if all characters in S are alphabetic
136         and there is at least one character in S, False otherwise.
137         """
138         return False
139 
140     def isdigit(self):  
141         """ 是否是数字 """
142         """
143         S.isdigit() -> bool
144         
145         Return True if all characters in S are digits
146         and there is at least one character in S, False otherwise.
147         """
148         return False
149 
150     def islower(self):  
151         """ 是否小写 """
152         """
153         S.islower() -> bool
154         
155         Return True if all cased characters in S are lowercase and there is
156         at least one cased character in S, False otherwise.
157         """
158         return False
159 
160     def isspace(self):  
161         """
162         S.isspace() -> bool
163         
164         Return True if all characters in S are whitespace
165         and there is at least one character in S, False otherwise.
166         """
167         return False
168 
169     def istitle(self):  
170         """
171         S.istitle() -> bool
172         
173         Return True if S is a titlecased string and there is at least one
174         character in S, i.e. uppercase characters may only follow uncased
175         characters and lowercase characters only cased ones. Return False
176         otherwise.
177         """
178         return False
179 
180     def isupper(self):  
181         """
182         S.isupper() -> bool
183         
184         Return True if all cased characters in S are uppercase and there is
185         at least one cased character in S, False otherwise.
186         """
187         return False
188 
189     def join(self, iterable):  
190         """ 连接 """
191         """
192         S.join(iterable) -> string
193         
194         Return a string which is the concatenation of the strings in the
195         iterable.  The separator between elements is S.
196         """
197         return ""
198 
199     def ljust(self, width, fillchar=None):  
200         """ 内容左对齐,右侧填充 """
201         """
202         S.ljust(width[, fillchar]) -> string
203         
204         Return S left-justified in a string of length width. Padding is
205         done using the specified fill character (default is a space).
206         """
207         return ""
208 
209     def lower(self):  
210         """ 变小写 """
211         """
212         S.lower() -> string
213         
214         Return a copy of the string S converted to lowercase.
215         """
216         return ""
217 
218     def lstrip(self, chars=None):  
219         """ 移除左侧空白 """
220         """
221         S.lstrip([chars]) -> string or unicode
222         
223         Return a copy of the string S with leading whitespace removed.
224         If chars is given and not None, remove characters in chars instead.
225         If chars is unicode, S will be converted to unicode before stripping
226         """
227         return ""
228 
229     def partition(self, sep):  
230         """ 分割,前,中,后三部分 """
231         """
232         S.partition(sep) -> (head, sep, tail)
233         
234         Search for the separator sep in S, and return the part before it,
235         the separator itself, and the part after it.  If the separator is not
236         found, return S and two empty strings.
237         """
238         pass
239 
240     def replace(self, old, new, count=None):  
241         """ 替换 """
242         """
243         S.replace(old, new[, count]) -> string
244         
245         Return a copy of string S with all occurrences of substring
246         old replaced by new.  If the optional argument count is
247         given, only the first count occurrences are replaced.
248         """
249         return ""
250 
251     def rfind(self, sub, start=None, end=None):  
252         """
253         S.rfind(sub [,start [,end]]) -> int
254         
255         Return the highest index in S where substring sub is found,
256         such that sub is contained within S[start:end].  Optional
257         arguments start and end are interpreted as in slice notation.
258         
259         Return -1 on failure.
260         """
261         return 0
262 
263     def rindex(self, sub, start=None, end=None):  
264         """
265         S.rindex(sub [,start [,end]]) -> int
266         
267         Like S.rfind() but raise ValueError when the substring is not found.
268         """
269         return 0
270 
271     def rjust(self, width, fillchar=None):  
272         """
273         S.rjust(width[, fillchar]) -> string
274         
275         Return S right-justified in a string of length width. Padding is
276         done using the specified fill character (default is a space)
277         """
278         return ""
279 
280     def rpartition(self, sep):  
281         """
282         S.rpartition(sep) -> (head, sep, tail)
283         
284         Search for the separator sep in S, starting at the end of S, and return
285         the part before it, the separator itself, and the part after it.  If the
286         separator is not found, return two empty strings and S.
287         """
288         pass
289 
290     def rsplit(self, sep=None, maxsplit=None):  
291         """
292         S.rsplit([sep [,maxsplit]]) -> list of strings
293         
294         Return a list of the words in the string S, using sep as the
295         delimiter string, starting at the end of the string and working
296         to the front.  If maxsplit is given, at most maxsplit splits are
297         done. If sep is not specified or is None, any whitespace string
298         is a separator.
299         """
300         return []
301 
302     def rstrip(self, chars=None):  
303         """
304         S.rstrip([chars]) -> string or unicode
305         
306         Return a copy of the string S with trailing whitespace removed.
307         If chars is given and not None, remove characters in chars instead.
308         If chars is unicode, S will be converted to unicode before stripping
309         """
310         return ""
311 
312     def split(self, sep=None, maxsplit=None):  
313         """ 分割, maxsplit最多分割几次 """
314         """
315         S.split([sep [,maxsplit]]) -> list of strings
316         
317         Return a list of the words in the string S, using sep as the
318         delimiter string.  If maxsplit is given, at most maxsplit
319         splits are done. If sep is not specified or is None, any
320         whitespace string is a separator and empty strings are removed
321         from the result.
322         """
323         return []
324 
325     def splitlines(self, keepends=False):  
326         """ 根据换行分割 """
327         """
328         S.splitlines(keepends=False) -> list of strings
329         
330         Return a list of the lines in S, breaking at line boundaries.
331         Line breaks are not included in the resulting list unless keepends
332         is given and true.
333         """
334         return []
335 
336     def startswith(self, prefix, start=None, end=None):  
337         """ 是否起始 """
338         """
339         S.startswith(prefix[, start[, end]]) -> bool
340         
341         Return True if S starts with the specified prefix, False otherwise.
342         With optional start, test S beginning at that position.
343         With optional end, stop comparing S at that position.
344         prefix can also be a tuple of strings to try.
345         """
346         return False
347 
348     def strip(self, chars=None):  
349         """ 移除两段空白 """
350         """
351         S.strip([chars]) -> string or unicode
352         
353         Return a copy of the string S with leading and trailing
354         whitespace removed.
355         If chars is given and not None, remove characters in chars instead.
356         If chars is unicode, S will be converted to unicode before stripping
357         """
358         return ""
359 
360     def swapcase(self):  
361         """ 大写变小写,小写变大写 """
362         """
363         S.swapcase() -> string
364         
365         Return a copy of the string S with uppercase characters
366         converted to lowercase and vice versa.
367         """
368         return ""
369 
370     def title(self):  
371         """
372         S.title() -> string
373         
374         Return a titlecased version of S, i.e. words start with uppercase
375         characters, all remaining cased characters have lowercase.
376         """
377         return ""
378 
379     def translate(self, table, deletechars=None):  
380         """
381         转换,需要先做一个对应表,最后一个表示删除字符集合
382         intab = "aeiou"
383         outtab = "12345"
384         trantab = maketrans(intab, outtab)
385         str = "this is string example....wow!!!"
386         print str.translate(trantab, 'xm')
387         """
388 
389         """
390         S.translate(table [,deletechars]) -> string
391         
392         Return a copy of the string S, where all characters occurring
393         in the optional argument deletechars are removed, and the
394         remaining characters have been mapped through the given
395         translation table, which must be a string of length 256 or None.
396         If the table argument is None, no translation is applied and
397         the operation simply removes the characters in deletechars.
398         """
399         return ""
400 
401     def upper(self):  
402         """
403         S.upper() -> string
404         
405         Return a copy of the string S converted to uppercase.
406         """
407         return ""
408 
409     def zfill(self, width):  
410         """方法返回指定长度的字符串,原字符串右对齐,前面填充0。"""
411         """
412         S.zfill(width) -> string
413         
414         Pad a numeric string S with zeros on the left, to fill a field
415         of the specified width.  The string S is never truncated.
416         """
417         return ""
418 
419     def _formatter_field_name_split(self, *args, **kwargs): # real signature unknown
420         pass
421 
422     def _formatter_parser(self, *args, **kwargs): # real signature unknown
423         pass
424 
425     def __add__(self, y):  
426         """ x.__add__(y) <==> x+y """
427         pass
428 
429     def __contains__(self, y):  
430         """ x.__contains__(y) <==> y in x """
431         pass
432 
433     def __eq__(self, y):  
434         """ x.__eq__(y) <==> x==y """
435         pass
436 
437     def __format__(self, format_spec):  
438         """
439         S.__format__(format_spec) -> string
440         
441         Return a formatted version of S as described by format_spec.
442         """
443         return ""
444 
445     def __getattribute__(self, name):  
446         """ x.__getattribute__('name') <==> x.name """
447         pass
448 
449     def __getitem__(self, y):  
450         """ x.__getitem__(y) <==> x[y] """
451         pass
452 
453     def __getnewargs__(self, *args, **kwargs): # real signature unknown
454         pass
455 
456     def __getslice__(self, i, j):  
457         """
458         x.__getslice__(i, j) <==> x[i:j]
459                    
460                    Use of negative indices is not supported.
461         """
462         pass
463 
464     def __ge__(self, y):  
465         """ x.__ge__(y) <==> x>=y """
466         pass
467 
468     def __gt__(self, y):  
469         """ x.__gt__(y) <==> x>y """
470         pass
471 
472     def __hash__(self):  
473         """ x.__hash__() <==> hash(x) """
474         pass
475 
476     def __init__(self, string=''): # known special case of str.__init__
477         """
478         str(object='') -> string
479         
480         Return a nice string representation of the object.
481         If the argument is a string, the return value is the same object.
482         # (copied from class doc)
483         """
484         pass
485 
486     def __len__(self):  
487         """ x.__len__() <==> len(x) """
488         pass
489 
490     def __le__(self, y):  
491         """ x.__le__(y) <==> x<=y """
492         pass
493 
494     def __lt__(self, y):  
495         """ x.__lt__(y) <==> x<y """
496         pass
497 
498     def __mod__(self, y):  
499         """ x.__mod__(y) <==> x%y """
500         pass
501 
502     def __mul__(self, n):  
503         """ x.__mul__(n) <==> x*n """
504         pass
505 
506     @staticmethod # known case of __new__
507     def __new__(S, *more):  
508         """ T.__new__(S, ...) -> a new object with type S, a subtype of T """
509         pass
510 
511     def __ne__(self, y):  
512         """ x.__ne__(y) <==> x!=y """
513         pass
514 
515     def __repr__(self):  
516         """ x.__repr__() <==> repr(x) """
517         pass
518 
519     def __rmod__(self, y):  
520         """ x.__rmod__(y) <==> y%x """
521         pass
522 
523     def __rmul__(self, n):  
524         """ x.__rmul__(n) <==> n*x """
525         pass
526 
527     def __sizeof__(self):  
528         """ S.__sizeof__() -> size of S in memory, in bytes """
529         pass
530 
531     def __str__(self):  
532         """ x.__str__() <==> str(x) """
533         pass
534 
535 str
536 
537 str
View Code

 常用方法:

str.strip() #开始和结尾去除空格或者字符
str.lstrip() #开始
str.rstrip()#结尾
去两侧的空格及符号

>>> l = '   jdq    '
>>> l.strip()
'jdq'

>>> l1 = '(jdq)'

>>> l1.strip('()') #去除字符串左右的括号
'jdq'

>>> l3.strip('q')
'jd'

 

字符串连接
方法1: 用字符串的join方法
a = ['a','b','c','d']
content = ''
content = ''.join(a)
print(content)
方法2: 用字符串的替换占位符替换
a = ['a','b','c','d']
content = ''
content = '%s%s%s%s' % tuple(a)
print (content)

引申出字符串格式化输出

我们格式化构建字符串可以有3种方法:
1 元组占位符
m = 'python'
astr = 'i love %s' % m
print(astr)

2 字符串的format方法
m = 'python'
astr = "i love {python}".format(python=m)
print(astr)

3 字典格式化字符串
m = 'python'
astr = "i love %(python)s " % {'python':m}
print(astr)

大家可以根据自己的实际情况来选择合适的方法,推荐用字符串的format方法或者字典的占位格式化,因为它不会受参数的位置影响,只需要参数名称相同就行。

字符串截取
我们可以通过索引来提取想要获取的字符,可以把python的字符串也做为字符串的列表就更好理解

python的字串列表有2种取值顺序
1是从左到右索引默认0开始的,最大范围是字符串长度少1
s = 'ilovepython'
s[0]的结果是i

2是从右到左索引默认-1开始的,最大范围是字符串开头
s = 'ilovepython'
s[-1]的结果是n

上面这个是取得一个字符,如果你的实际要取得一段子串的话,可以用到变量[头下标:尾下标],就可以截取相应的字符串,其中下标是从0开始算起,可以是正数或负数,下标可以为空表示取到头或尾。

比如
s = 'ilovepython'
s[1:5]的结果是love
当使用以冒号分隔的字符串,python返回一个新的对象,结果包含了以这对偏移标识的连续的内容,左边的开始是包含了下边界,比如
上面的结果包含了s[1]的值l,而取到的最大范围不包括上边界,就是s[5]的值p

字符串替换
字符串替换可以用内置的方法和正则表达式完成。
1用字符串本身的replace方法:
a = 'hello word'
b = a.replace('word','python')
print(b)
2用正则表达式来完成替换:
import re
a = 'hello word'
strinfo = re.compile('word')
b = strinfo.sub('python',a)
print(b)

字符串查找
python 字符串查找有4个方法,1 find,2 index方法,3 rfind方法,4 rindex方法。
1 find()方法:
info = 'abca'
print(info.find('a')) ##从下标0开始,查找在字符串里第一个出现的子串,返回结果:0

info = 'abca'
print(info.find('a',1)) ##从下标1开始,查找在字符串里第一个出现的子串:返回结果3

info = 'abca'
print(info.find('333')) ##返回-1,查找不到返回-1
2 index()方法:
python 的index方法是在字符串里查找子串第一次出现的位置,类似字符串的find方法,不过比find方法不同的是,如果查找不到子串,会抛出异常,而不是返回-1
info = 'abca'
print(info.index('a',1)) #3
print(info.index('33'))  #ValueError: substring not found

字符串分割
字符串分割,可以用split,rsplit方法,通过相应的规则来切割成生成列表对象
记住:分割字符会被去除
info = 'name:haha,age:20$name:python,age:30$name:fef,age:55'
content = info.split('$')
print(content) #['name:haha,age:20', 'name:python,age:30', 'name:fef,age:55']

字符串翻转
通过步进反转[::-1]
a = 'abcd'
b = a[::-1]##[::-1]通过步进反转
print(b)

字符串编码
在新版本的python3中,取消了unicode类型,代替它的是使用unicode字符的字符串类型(str),字符串类型(str)成为基础类型如下所示,而编码后的变为了字节类型(bytes)但是两个函数的使用方法不变:

decode encode

bytes ------> str(unicode)------>bytes
a = '你好'
print(a.encode('utf-8').decode('utf-8'))

 

字符串大小写
通过下面的upper(),lower()等方法来转换大小写
S.upper()#S中的字母大写
S.lower() #S中的字母小写
S.capitalize() #首字母大写
S.istitle() #S是否是首字母大写的
S.isupper() #S中的字母是否便是大写
S.islower() #S中的字母是否全是小写

字符串其他方法
字符串相关的其他方法:count(),join()方法等。
S.center(width, [fillchar]) #中间对齐
S.count(substr, [start, [end]]) #计算substr在S中出现的次数
S.expandtabs([tabsize]) #把S中的tab字符替换没空格,每个tab替换为tabsize个空格,默认是8个
S.isalnum() #是否全是字母和数字,并至少有一个字符
S.isalpha() #是否全是字母,并至少有一个字符
S.isspace() #是否全是空白字符,并至少有一个字符
S.join()#S中的join,把列表生成一个字符串对象
S.ljust(width,[fillchar]) #输出width个字符,S左对齐,不足部分用fillchar填充,默认的为空格。
S.rjust(width,[fillchar]) #右对齐
S.splitlines([keepends]) #把S按照行分割符分为一个list,keepends是一个bool值,如果为真每行后而会保留行分割符。
S.swapcase() #大小写互换

 

partition(str) 方法用来根据指定的分隔符将字符串进行分割。
如果字符串包含指定的分隔符,则返回一个3元的元组,第一个为分隔符左边的子串,第二个为分隔符本身,第三个为分隔符右边的子串。

问题:你需要将一个字符串分割为多个字段,但是分隔符 (还有周围的空格) 并不是固定的。
string 对象的 split() 方法只适应于非常简单的字符串分割情形,它并不允许有多个分隔符或者是分隔符周围不确定的空格。当你需要更加灵活的切割字符串的时候,最好使用 re.split() 方法:
>>> line = 'asdf fjdk; afed, fjek,asdf, foo'
>>> import re
>>> re.split(r'[;,\s]\s*', line)
['asdf', 'fjdk', 'afed', 'fjek', 'asdf', 'foo']

函数re.split()是非常实用的,因为它允许你为分隔符指定多个正则模式。比如,在上面的例子中,分隔符可以是逗号,分号或者是空格,并且后面紧跟着任意个
的空格。只要这个模式被找到,那么匹配的分隔符两边的实体都会被当成是结果中的元素返回。返回结果为一个字段列表,这个跟str.split()返回值类型是一样的。

当你使用 re.split() 函数时候,需要特别注意的是正则表达式中是否包含一个括
号捕获分组。如果使用了捕获分组,那么被匹配的文本也将出现在结果列表中。比如,
观察一下这段代码运行后的结果:
>>> fields = re.split(r'(;|,|\s)\s*', line)
>>> fields
['asdf', ' ', 'fjdk', ';', 'afed', ',', 'fjek', ',', 'asdf', ',', 'foo']
>>>

当你使用re.split()函数时候,需要特别注意的是正则表达式中是否包含一个括号捕获分组。如果使用了捕获分组,那么被匹配的文本也将出现在结果列表中。比如,观察一下这段代码运行后的结果:
>>> fields = re.split(r'(;|,|\s)\s*', line)
>>> fields
['asdf', ' ', 'fjdk', ';', 'afed', ',', 'fjek', ',', 'asdf', ',', 'foo']
>>>

获取分割字符在某些情况下也是有用的。比如,你可能想保留分割字符串,用来在后面重新构造一个新的输出字符串:
>>> values = fields[::2]
>>> delimiters = fields[1::2] + ['']
>>> values
['asdf', 'fjdk', 'afed', 'fjek', 'asdf', 'foo']
>>> delimiters
[' ', ';', ',', ',', ',', '']
>>> ''.join(v+d for v,d in zip(values, delimiters))
'asdf fjdk;afed,fjek,asdf,foo'
>>>

问题:你需要通过指定的文本模式去检查字符串的开头或者结尾,比如文件名后缀,URLScheme 等等
检查字符串开头或结尾的一个简单方法是使用str.startswith()或者是str.endswith() 方法。比如:
>>> filename = 'spam.txt'
>>> filename.endswith('.txt')
True
>>> filename.startswith('file:')
False
>>> url = 'http://www.python.org
>>> url.startswith('http:')
True

如果你想检查多种匹配可能,只需要将所有的匹配项放入到一个元组中去,然后传给 startswith() 或者 endswith() 方法:
>>> import os
>>> filenames = os.listdir('.')
>>> filenames
[ 'Makefile', 'foo.c', 'bar.py', 'spam.c', 'spam.h' ]
>>> [name for name in filenames if name.endswith(('.c', '.h')) ]
['foo.c', 'spam.c', 'spam.h'
>>> any(name.endswith('.py') for name in filenames)
True

下面是另一个例子:
from urllib.request import urlopen
def read_data(name):
if name.startswith(('http:', 'https:', 'ftp:')):
return urlopen(name).read()
else:
with open(name) as f:
return f.read()
奇怪的是,这个方法中必须要输入一个元组作为参数。如果你恰巧有一个list 或者set类型的选择项,要确保传递参数前先调用tuple()将其转换为元组类型。比如:
>>> choices = ['http:', 'ftp:']
>>> url = 'http://www.python.org'
>>> url.startswith(choices)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: startswith first arg must be str or a tuple of str, not list
>>> url.startswith(tuple(choices))
True
最后提一下,当和其他操作比如普通数据聚合相结合的时候 startswith() 和endswith()方法是很不错的。比如,下面这个语句检查某个文件夹中是否存在指定的文件类型:
if any(name.endswith(('.c', '.h')) for name in listdir(dirname)):
...

问题:你想使用 Unix Shell 中常用的通配符 (比如 *.py , Dat[0-9]*.csv 等) 去匹配文本字符串
fnmatch 模块提供了两个函数—— fnmatch() 和 fnmatchcase() ,可以用来实现这样的匹配。用法如下:
>>> from fnmatch import fnmatch, fnmatchcase
>>> fnmatch('foo.txt', '*.txt')
True
>>> fnmatch('foo.txt', '?oo.txt')
True
>>> fnmatch('Dat45.csv', 'Dat[0-9]*')
True
>>> names = ['Dat1.csv', 'Dat2.csv', 'config.ini', 'foo.py']
>>> [name for name in names if fnmatch(name, 'Dat*.csv')]
['Dat1.csv', 'Dat2.csv']
>>>
fnmatch() 函数使用底层操作系统的大小写敏感规则 (不同的系统是不一样的) 来匹配模式。
如果你对这个区别很在意,可以使用 fnmatchcase() 来代替。它完全使用你的模式大小写匹配。比如:
>>> fnmatchcase('foo.txt', '*.TXT')
False
>>>
这两个函数通常会被忽略的一个特性是在处理非文件名的字符串时候它们也是很有用的。比如,假设你有一个街道地址的列表数据:
addresses = [
'5412 N CLARK ST',
'1060 W ADDISON ST',
'1039 W GRANVILLE AVE',
'2122 N CLARK ST',
'4802 N BROADWAY',
]
你可以像这样写列表推导:
>>> from fnmatch import fnmatchcase
>>> [addr for addr in addresses if fnmatchcase(addr, '* ST')]
['5412 N CLARK ST', '1060 W ADDISON ST', '2122 N CLARK ST']
>>> [addr for addr in addresses if fnmatchcase(addr, '54[0-9][0-9] *CLARK*')]
['5412 N CLARK ST']
>>>

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

字符串搜索和替换
对于简单的字面模式,直接使用 str.repalce() 方法即可,比如:
>>> text = 'yeah, but no, but yeah, but no, but yeah'
>>> text.replace('yeah', 'yep')
'yep, but no, but yep, but no, but yep'
>>>
对于复杂的模式,请使用 re 模块中的 sub() 函数。为了说明这个,假设你想将形式为 11/27/201 的日期字符串改成 2012-11-27 。示例如下:
>>> text = 'Today is 11/27/2012. PyCon starts 3/13/2013.'
>>> import re
>>> re.sub(r'(\d+)/(\d+)/(\d+)', r'\3-\1-\2', text)
'Today is 2012-11-27. PyCon starts 2013-3-13.'
>>>
sub() 函数中的第一个参数是被匹配的模式,第二个参数是替换模式。反斜杠数字比如 \3 指向前面模式的捕获组号。

最短匹配模式
这个问题一般出现在需要匹配一对分隔符之间的文本的时候 (比如引号包含的字符串)。为了说明清楚,考虑如下的例子:
>>> str_pat = re.compile(r'\"(.*)\"')
>>> text1 = 'Computer says "no."'
>>> str_pat.findall(text1)
['no.']
>>> text2 = 'Computer says "no." Phone says "yes."'
>>> str_pat.findall(text2)
['no." Phone says "yes.']
>>>
在这个例子中,模式 r'\"(.*)\"' 的意图是匹配被双引号包含的文本。但是在正则表达式中 * 操作符是贪婪的,因此匹配操作会查找最长的可能匹配。于是在第二个例子中搜索 text2 的时候返回结果并不是我们想要的。为了修正这个问题,可以在模式中的 * 操作符后面加上? 修饰符,就像这样:
>>> str_pat = re.compile(r'\"(.*?)\"')
>>> str_pat.findall(text2)
['no.', 'yes.']
>>>
这样就使得匹配变成非贪婪模式,从而得到最短的匹配,也就是我们想要的结果。

posted @ 2016-03-13 23:01  sunjdq  阅读(331)  评论(0编辑  收藏  举报