共58 次浏览

第五章 字符串与正则表达式

5.1字符串的常用操作

5.1.1字符串拼接

字符串的重要性不言而喻,在之前学习JavaScript的过程中也有很多字符串的相关问题。在Python中,字符串的作用也非常大,因此需要不断地总结和学习。首先是字符串拼接,使用加号(+)运算符可以将两个字符串拼接起来,成为一个新的字符串。使用方法很简单,我们之前在java和JavaScript中都有接触到字符串的拼接,但是在这里字符串的拼接需要注意的是两者类型必须都是字符串,否则会报错,如果需要将字符串和其它类型的拼接在一起的话则需要对其它类型的变量进行强制类型转换,使用str()函数,让其成为字符串,然后再进行相加。

5.1.2计算字符串的长度

在Python语言中,数字、英文、小数点、下划线和空格各占1个字节。汉字可能会占2~4个字节,占几字节屈居用采用的编码格式。由于Python语言默认采用UTF-8编码,所以汉字占有3个字节。Python语言通过len( )函数计算字符串的长度,len( )在计算字符串长度时,并不区英文和中文,统统按照一个字符进行计算。如果用户需要获取字符串的实际所占字节数,就需要指定编码。然后才能获取实际的长度。

 >>>s1="我今天需要参加English考试。"  #包含了英文、中文和标点符号的字符串。
 >>>ls=len(s1)       #定义字符串的长度
 >>> ls
 17
 #--------------------------
 >>>s1="我今天需要参加English考试。" #包含了英文、中文和标点符号的字符串。
 >>>ls=len(s1.encode())       #定义字符串的长度
 >>> ls
 37

在上面这段代码中,字符串共有9个汉字和一个中文标点符号,占30个字节,英文共有7个,所以结果为37。

5.1.3截取字符串

与列表一样,索引都是从0开始。Python访问子字符串变量,可以使用中括号([])和冒号(:)来截取字符串。使用方法 : a[x,y]

截取的字符串从x索引位置开始,到y结束,它的范围为左闭右开,即[x,y)。如果没有x则代表从0开始,如果没有y,则代表从x开始,到结尾,如果想要截取字符串全部,则x和y都不用给值,者在之前的del中就用到过。

5.1.4 分割和合并字符串

1.在Python语言中,通过split( )方法通过指定分隔符对字符串进行分割(切片),该方法的语法格式如下:

 str.split(str="",num=string.count(str))

在JavaScript中也有split( )函数,它的第一个参数是一个分隔符或者是正则表达式,第二个参数表示分割后的数组的最大长度。本质上来说与python中的split效果是一样的。都是对字符串进行分割操作。

2.合并字符串

join( )方法用于将序列中的元素以指定的字符合并生成一个新的字符串,需要注意的是被合并的元素必须是字符串。

 >>>s1="*"
 >>>e1=('不','破','楼','兰','终','不','还')
 >>>print(s1.join(e1))
 不*破*楼*兰*终*不*还

5.1.5检索字符串

  1. count( )
    count( )方法用于统计字符串里某个字符出现的次数,可选参数为在字符串检索的开始与结束位置。 语法格式:str.count(sub,strart=0,end=len(string)),如果缺少则默认是整个字符串。
  2. find( )方法
    find( )方法检索字符串中是否包含子字符串。如果包含该子字符串,就返回该字符串开始的索引值,否则就返回-1。这与JavaScript中的indexOf方法类似,都是检测字串是否在该字符串中,并返回第一次出现的位置。find( )方法同样也支持检索参数,即开始的位置到截至的位置索引,与前面的使用方法相同,范围也都是左闭右开。
  3. index( )方法
    index( )方法用于尖子字符串中是否包含子字符串,如果包含则返回开始位置的索引,否则就会报错。这个方法同样也支持开始的查询位置和截至的位置。

5.1.6字母的大小写转换

在Python中字符串的大小写转换函数是upper( )和low( ),使用方法与JavaScript中的toLowerCase( )和toUpperCase( )的方法相同,所以在这里不做过多解释

5.1.7删除字符串中的空格和特殊字符

  1. strip( )方法
    strip( )方法用于删除字符串头尾指定的字符或字符序列。需要注意的是该方法只能删除开头或结尾的字符,不能删除中间的字符。使用方法:str.strip([chars]),参数chars是需要删除的字符序列,默认情况下是空格。该方法的返回值为删除指定字符后生成的新字符串。 >>>str=”*****茅檐**低小**,溪上青青草。*****”
     >>>print(str.strip('*')) #会删除开头和结尾的'*'.
     ‘茅檐**低小**,溪上草青青。’
  2. lstrip( )方法
    lstrip( )方法用于截掉字符串左边的空格或指定字符。如果未指定参数,则默认情况下是空格。这个就相当于strip( )的缩小版,只会删除字符串左边的字符。
  3. rstrip( )方法
    通过名字我们也可以看出,这个方法是以 ‘r’ 开头的,所以会删除字符串末尾的指定字符,默认情况下是空格。

5.1.8使用Python的转义字符

有时候需要在字符串内设置单引号、双引号、换行符等,在此时就可以使用转义字符。Python的转义字符是由一个反斜杠()和一个字符组成

image-20210402231633558

换行符,\n与我们在C语言中的使用方法相同,在双引号中直接输入就可实现换行。如果要输出双引号,则直接在双引号之前加上反斜杠() 就可以实现。各进制同样也可以使用。

5.2字符串的编码转换

在Python中,有两种常用的字符串类型,分别为str和bytes。其中,str表示Unicode字符;bytes表示二进制数。这两种类型的字符不能拼接在一起使用。一个字符对应若干个字节。如果在网上上传输或者保存在磁盘上,就需要把str转换成bytes类型,即字节型

str类型和bytes类型之间可以通过encode( )和decode( )方法进行转换,这两个方法的转换是可逆的。

 #coding:utf-8
 s = "你好,中国!" 
 print(s)     # Python2输出乱码,Python3正常输出
 print(type(s))    # 均输出 <type 'str'>
 ​
 #解码成unicode
 s1 = s.decode("utf-8")
 print(s1)    # Python2中输出 “你好,中国!”,Python3显示'str'对象没有属性'decode'
 print(type(s1))   # Python2中输出 <type 'unicode'>  Python3中输出 <class 'str'> 
 ​
 #编码成gbk 或 utf-8
 s2 = s1.encode('gbk')
 print(s2)      # Python2中输出 “你好,中国!”
 print(type(s2))    # Python2中输出 <type 'str'>
 s3 = s1.encode('utf-8')
 print(s3)      # Python2输出乱码,
 print(type(s3))    # 输出 <type 'str'>
image-20210402233012990

5.3正则表达式和re模块

正则表达式是字符串,它包含文本和特殊字符。re模块可以执行正则表达式的功能。文字与特定字符的混合,可以定义复杂的字符串匹配与取代功能

qq_pic_merged_1617410899232
字符描述
\将下一个字符标记为一个特殊字符、或一个原义字符、或一个 向后引用、或一个八进制转义符。例如,’n’ 匹配字符 “n”。’\n’ 匹配一个换行符。序列 ‘\’ 匹配 “” 而 “(” 则匹配 “(“。
^匹配输入字符串的开始位置。如果设置了 RegExp 对象的 Multiline 属性,^ 也匹配 ‘\n’ 或 ‘\r’ 之后的位置。
$匹配输入字符串的结束位置。如果设置了RegExp 对象的 Multiline 属性,$ 也匹配 ‘\n’ 或 ‘\r’ 之前的位置。
*匹配前面的子表达式零次或多次。例如,zo* 能匹配 “z” 以及 “zoo”。* 等价于{0,}。
+匹配前面的子表达式一次或多次。例如,’zo+’ 能匹配 “zo” 以及 “zoo”,但不能匹配 “z”。+ 等价于 {1,}。
?匹配前面的子表达式零次或一次。例如,”do(es)?” 可以匹配 “do” 或 “does” 中的”do” 。? 等价于 {0,1}。
{n}n 是一个非负整数。匹配确定的 n 次。例如,’o{2}’ 不能匹配 “Bob” 中的 ‘o’,但是能匹配 “food” 中的两个 o。
{n,}n 是一个非负整数。至少匹配n 次。例如,’o{2,}’ 不能匹配 “Bob” 中的 ‘o’,但能匹配 “foooood” 中的所有 o。’o{1,}’ 等价于 ‘o+’。’o{0,}’ 则等价于 ‘o*’。
{n,m}m 和 n 均为非负整数,其中n <= m。最少匹配 n 次且最多匹配 m 次。例如,”o{1,3}” 将匹配 “fooooood” 中的前三个 o。’o{0,1}’ 等价于 ‘o?’。请注意在逗号和两个数之间不能有空格。
?当该字符紧跟在任何一个其他限制符 (*, +, ?, {n}, {n,}, {n,m}) 后面时,匹配模式是非贪婪的。非贪婪模式尽可能少的匹配所搜索的字符串,而默认的贪婪模式则尽可能多的匹配所搜索的字符串。例如,对于字符串 “oooo”,’o+?’ 将匹配单个 “o”,而 ‘o+’ 将匹配所有 ‘o’。
.匹配除 “\n” 之外的任何单个字符。要匹配包括 ‘\n’ 在内的任何字符,请使用象 ‘[.\n]’ 的模式。
(pattern)匹配 pattern 并获取这一匹配。所获取的匹配可以从产生的 Matches 集合得到,在VBScript 中使用 SubMatches 集合,在JScript 中则使用 $0…$9 属性。要匹配圆括号字符,请使用 ‘(‘ 或 ‘)’。
(?:pattern)匹配 pattern 但不获取匹配结果,也就是说这是一个非获取匹配,不进行存储供以后使用。这在使用 “或” 字符 (|) 来组合一个模式的各个部分是很有用。例如, ‘industr(?:y|ies) 就是一个比 ‘industry|industries’ 更简略的表达式。
(?=pattern)正向预查,在任何匹配 pattern 的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如,’Windows (?=95|98|NT|2000)’ 能匹配 “Windows 2000” 中的 “Windows” ,但不能匹配 “Windows 3.1” 中的 “Windows”。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始。
(?!pattern)负向预查,在任何不匹配 pattern 的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如’Windows (?!95|98|NT|2000)’ 能匹配 “Windows 3.1” 中的 “Windows”,但不能匹配 “Windows 2000” 中的 “Windows”。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始
x|y匹配 x 或 y。例如,’z|food’ 能匹配 “z” 或 “food”。'(z|f)ood’ 则匹配 “zood” 或 “food”。
[xyz]字符集合。匹配所包含的任意一个字符。例如, ‘[abc]’ 可以匹配 “plain” 中的 ‘a’。
[^xyz]负值字符集合。匹配未包含的任意字符。例如, ‘abc‘ 可以匹配 “plain” 中的’p’。
[a-z]字符范围。匹配指定范围内的任意字符。例如,'[a-z]’ 可以匹配 ‘a’ 到 ‘z’ 范围内的任意小写字母字符。
[^a-z]负值字符范围。匹配任何不在指定范围内的任意字符。例如,’a-z‘ 可以匹配任何不在 ‘a’ 到 ‘z’ 范围内的任意字符。
\b匹配一个单词边界,也就是指单词和空格间的位置。例如, ‘er\b’ 可以匹配”never” 中的 ‘er’,但不能匹配 “verb” 中的 ‘er’。
\B匹配非单词边界。’er\B’ 能匹配 “verb” 中的 ‘er’,但不能匹配 “never” 中的 ‘er’。
\cx匹配由 x 指明的控制字符。例如, \cM 匹配一个 Control-M 或回车符。x 的值必须为 A-Z 或 a-z 之一。否则,将 c 视为一个原义的 ‘c’ 字符。
\d匹配一个数字字符。等价于 [0-9]。
\D匹配一个非数字字符。等价于 0-9
\f匹配一个换页符。等价于 \x0c 和 \cL。
\n匹配一个换行符。等价于 \x0a 和 \cJ。
\r匹配一个回车符。等价于 \x0d 和 \cM。
\s匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]。
\S匹配任何非空白字符。等价于 \f\n\r\t\v
\t匹配一个制表符。等价于 \x09 和 \cI。
\v匹配一个垂直制表符。等价于 \x0b 和 \cK。
\w匹配包括下划线的任何单词字符。等价于'[A-Za-z0-9_]’。
\W匹配任何非单词字符。等价于 ‘A-Za-z0-9_‘。
\xn匹配 n,其中 n 为十六进制转义值。十六进制转义值必须为确定的两个数字长。例如,’\x41′ 匹配 “A”。’\x041′ 则等价于 ‘\x04’ & “1”。正则表达式中可以使用 ASCII 编码。.
\num匹配 num,其中 num 是一个正整数。对所获取的匹配的引用。例如,'(.)\1′ 匹配两个连续的相同字符。
\n标识一个八进制转义值或一个向后引用。如果 \n 之前至少 n 个获取的子表达式,则 n 为向后引用。否则,如果 n 为八进制数字 (0-7),则 n 为一个八进制转义值。
\nm标识一个八进制转义值或一个向后引用。如果 \nm 之前至少有 nm 个获得子表达式,则 nm 为向后引用。如果 \nm 之前至少有 n 个获取,则 n 为一个后跟文字 m 的向后引用。如果前面的条件都不满足,若 n 和 m 均为八进制数字 (0-7),则 \nm 将匹配八进制转义值 nm。
\nml如果 n 为八进制数字 (0-3),且 m 和 l 均为八进制数字 (0-7),则匹配八进制转义值 nml。
\un匹配 n,其中 n 是一个用四个十六进制数字表示的 Unicode 字符。例如, \u00A9 匹配版权符号 (?)。

5.3.2re模块的方法

re模块的主要功能是通过正则表达式来操作字符串。在使用re模块时,需要先引入re包。即 import re。

re模块中常见操作字符串的方法:

  1. 匹配字符串
    通过re模块的match( )、search( )和findall( )方法可以匹配字符串。
    ①match( )
    match( )方法用于从字符串的开始处进行匹配,如果在起始位置匹配成功,则返回Match对象;如果不是在起始位置匹配成功,则返回None。match( ) 的语法格式为: re.match(pattern,string,flags=0)第一个参数为匹配的正则表达式,第二个参数为需要匹配的字符串,第三个参数哟关于控制正则表达式的匹配方式,如是否区分大小写,多行匹配等。例如我们要检验输入的手机号是否为中国移动的手机号:第一个参数为匹配的正则表达式,第二个参数为需要匹配的字符串,第三个参数哟关于控制正则表达式的匹配方式,如是否区分大小写,多行匹配等。例如我们要检验输入的手机号是否为中国移动的手机号: 
    import re
     print("欢迎进入中国移动电话号码验证系统")
     s1=r'(13[4-9]\d{8})$|(15[01289]\d{8}$)'
     s2=input("请输入需要验证的电话号码:")
     match=re.match(s1,s2)
     if match==None:
      print("您输入的号码不是中国移动的号码")
     else:
      print("您输入的号码是中国移动的号码")

    ②search( )
    search( )方法用于扫描整个字符串并返回第一个成功的匹配。参数与match的参数意义相同。但与match( )不同的是,search( )方法既可以在起始位置匹配,也可以不在起始位置匹配。 需要注意的是match( )方法只匹配字符串的开始,如果字符串开始不符合正则表达式,则匹配失败,函数返回None;而search( )方法匹配整个字符串,直到找到一个匹配项。
    ③findall( )
    findall( )方法用于在字符串中找到正则表达式所匹配的所有子串,并返回一个列表,如果没有找到匹配项,则返回空列表。match( )和search( )只匹配一次,而findall( )方法匹配所有。findall( )语法格式: findall(sting[,pos[,endpos]])参数中string是待匹配的字符串,pos为可选参数,指定字符串的起始位置,默认为0;endpos为可选参数,指定字符串的结束位置,默认为字符串的长度。
  2. 替换字符串
    通过re模块中的sub( )方法可以替换字符串中的匹配项。语法格式如下: re.sub(pattern,repl,string,count=0,flags=0)参数中pattern是正则表达式中的模式字符串;repl是要替换的字符串,也可以为一个函数;参数string要被查找替换的原始字符串;参数count是模式匹配后替换的最大次数,默认为0。
  3. 分割字符串
    通过re模块中的split( )方法可以分割字符串。split( )方法按照能够匹配的子串将字符串分割后返回列表。语法格式如下: re.split(pattern,string[,maxsplit=0,flags=0])参数中pattern是正则表达式中的模式字符串;参数string为要被分割的字符串;参数maxsplit是分割次数,默认为0,不限制次数;参数flags用于控制正则表达式的匹配方式,如是否区分大小写、多行匹配等。 import re
     s1=”*张三丰*欧阳修*李白*颜真卿*齐白石”
     pattern = r’\*’
     ls = re.split(pattern,s1)  #以*分割字符串
     print(“您的标星好友是:”)
     for(im in ls):
      if im!=” “:
          print(im)

5.4格式化字符串

Python语言支持格式化字符串的输出。字符串格式化使用字符串操作符百分号(%)来实现。在百分号左侧放一个代格式化的字符串(格式化字符串),右侧放置希望被格式化的值。可以使用一个值,如一个字符串或数字,也可以使用多个值的元组或字典。

 age = 18
 print("赵日天已经%d岁了!" % age)
 #运行结果:
 赵日天已经18岁了!

当然,格式化字符串也可以包含多个转换说明符,这个时候需要提供多个表达式,用以替换对应的转换说明符;多个表达式必须使用小括号( )括起来

 name = "赵日天"
 age = 18
 url = "http://zx529.xyz"
 print("%s已经%d岁了,它的网址是%s。" % (name, age, url))
 #运行结果是:
 赵日天已经18岁了,它的网址是http://zx529.xyz

下面的表中列举出Python语言中字符串格式化符号

image-20210403115100311

其实在这里的格式化字符串与我们在C语言中学的比较接近,同时Python还支持指定最小输出宽度以及指定对齐方式、指定小数精度。

①指定最小输出宽度:

 n = 1234567
 print("n(10):%10d." % n)
 print("n(5):%5d." % n)
 ​
 url = "http://c.biancheng.net/python/"
 print("url(35):%35s." % url)
 print("url(20):%20s." % url)

使用表中的转换说明符,可以按照上面的格式指定最小输出宽度 。其中%10d表示输出的整数宽度至少为10.%20s 则表示输出的字符串宽度至少为20

②按照指定的小数精度输出:

 f = 3.141592653
 # 最小宽度为8,小数点后保留3位
 print("%8.3f" % f)
 # 最小宽度为8,小数点后保留3位,左边补0
 print("%08.3f" % f)
 # 最小宽度为8,小数点后保留3位,左边补0,带符号
 print("%+08.3f" % f)
 #输出的结果:
    3.142
 0003.142
 +003.142

③在Python中可以指定对齐方式
在默认情况下,print( )输出的数据总是右对齐的。也就是说,当数据的长度不够时,它总是右边对齐,而在左边补充空格来达到指定的宽度。Python允许在最小宽度之前增加一个标志来改变对齐方式,Python支持的标志如下:

image-20210403120206371

整数、小数以及字符串的对齐方式是有区别的。必须要在不改变他们大小以及有意义的前提下进行对齐。对于整数,指定左对齐时,在右边补0是没有效果的,因为会改变它的大小;对于小数,以上三个标志可以同时存在;对于字符串,则只能使用 – 因为符号对于字符串没有意义,而补0则会改变字符串的值。代码举例如下:

 n = 123456
 # %09d 表示最小宽度为9,左边补0
 print("n(09):%09d" % n)
 # %+9d 表示最小宽度为9,带上符号
 print("n(+9):%+9d" % n)
 ​
 f = 140.5
 # %-+010f 表示最小宽度为10,左对齐,带上符号
 print("f(-+0):%-+010f" % f)
 ​
 s = "Hello"
 # %-10s 表示最小宽度为10,左对齐
 print("s(-10):%-10s." % s)
 #运行结果为:
 n(09):000123456
 n(+9):  +123456
 f(-+0):+140.500000
 s(-10):Hello