第6章 字符串与正则表达式
6.1 字符串的操作
6.1.1 字符串的格式化
# 格式化字符串
str1 = "version"
num = 1.0
format = "%s" % str1
print format
format = "%s %d" % (str1, num)
print format
# 带精度的格式化
print "浮点型数字: %f" % 1.25 #默认情况下,将输出小数点后6位数字。
print "浮点型数字: %.1f" % 1.25
print "浮点型数字: %.2f" % 1.254
# 使用字典格式化字符串
print "%(version)s: %(num).1f" % {"version": "version", "num": 2} #在字典中定义了两个value 值
# 字符串对齐
word = "version3.0"
print word.center(20) #将字符串置于20个字符中间
print word.center(20, "*") #第二个参数指 填充 成 * 输出结果:*****version3.0*****
print word.ljust(0) # ljust 结果输出左对齐
print word.rjust(20) # rjust 结果输出右对齐
print "%30s" % word # 一个30个字符位置,先输出20上空格,再输出变量值。类似于:右对齐。</span>
6.1.2 字符串的转义符
# 输出转义字符
path = "hello\tworld\n" # \t 制表符 \n 换行符 其中各占一个字符
print path
print len(path)
path = r"hello\tworld\n" # 忽略转义字符的作用
print path
print len(path)
# strip()去掉转义字符
word = "\thello world\n"
print "直接输出:", word
print "strip()后输出:", word.strip()
print "lstrip()后输出:", word.lstrip()
print "rstrip()后输出:", word.rstrip()</span>
3、Python 还提供了函数strip( ) 、lstrip ( ) 、rstrip ( ) 去掉字符串中的转义符。
6.1.3 字符串的合并
# 使用join()连接字符串
strs = ["hello ", "world ", "hello ", "China "]
result = "".join(strs)
print result
# 使用reduce()连接字符串
import operator
strs = ["hello ", "world ", "hello ", "China "]
result = reduce(operator.add, strs, "") # reduce 实现对空字符串 “” 的累计连接,依次连接列表strs 中的一个元素。
print result</span>
6.1.4 字符串的截取
# 使用索引截取子串
word = "world"
print word[4] #输出:d
# 使用split()获取子串
sentence = "Bob said: 1, 2, 3, 4"
print "使用空格取子串:", sentence.split() #输出结果:使用空格取子串: ['Bob', 'said:', '1,', '2,', '3,', '4']
print "使用逗号取子串:", sentence.split(",") #输出:使用逗号取子串: ['Bob said: 1', ' 2', ' 3', ' 4']
print "使用两个逗号取子串:", sentence.split(",", 2) #输出:使用两个逗号取子串: ['Bob said: 1', ' 2', ' 3, 4']</span>
6.1.5 字符串的比较
# 字符串的比较
str1 = 1
str2 = "1"
if str1 == str2:
print "相同"
else:
print "不相同"
if str(str1) == str2:
print "相同"
else:
print "不相同"</span>
<span style="font-size:14px;"># 比较字符串的开始和结束处
word = "hello world"
print "hello" == word[0:5]
print word.startswith("hello")
print word.endswith("ld", 6)
print word.endswith("ld", 6, 10)
print word.endswith("ld", 6, len(word))</span>
6.1.6 字符串的反转
# 使用list的reverse()
def reverse(s):
li = list(s)
li.reverse()
s = "".join(li) # 连接列表字符串
return s
print reverse("hello")
# 循环输出反转的字符串
def reverse(s):
out = ""
li = list(s)
for i in range(len(li), 0, -1): # range ( start,stop,step)
out += "".join(li[i-1])
return out
print reverse("hello")
# 特殊切片反转字符串
def reverse(s):
return s[::-1] # 利用的是字符串的截取: string [ start,stop,step] 步长为-1,即从结尾到开始
print reverse("hello")
6.1.7 字符串的查找和替换
1、find ( ) 函数实现查找字符串功能。定义:find ( substring [ , start [ , end ] 参数substring 表示待查找的子串,如果找到字符串substring , 则返回substring 在源字符串中第1次出现的索引,否则返回 -1。 rfind ( ) 从字符串的尾部开始查找。
# 查找字符串
sentence = "This is a apple."
print sentence.find("a") # 输出 8
sentence = "This is a apple."
print sentence.rfind("a") # 输出 10
2、替换字符串 用 函数replace ( ) 实现。 声明:replace ( old , new [ , max ] ) old被替换的字符串,new表示替换old的字符串,参数max表示使用new替换old 的次数。函数返回一个新的字符串,如果old 不在源字符串,则返回源字符串的值。
# 字符串的替换
centence = "hello world, hello China"
print centence.replace("hello", "hi") #输出:hi world, hi China
print centence.replace("hello", "hi", 1) #输出:hi world, hello China
print centence.replace("abc", "hi") #输出:hello world, hello China
注意:replace ( ) 先创建变量centence的拷贝,在拷贝中替换,并不改变变量centence的的内容。
6.1.8 字符串与日期的转换
2、字符串到时间的转换
第一步:调用函数strptime ( ) 把字符串转换为一个元组,进行第1次转换。
strptime ( string , format ) ---> struct_time
参数string 表示需要转换的字符串,format 表示 日期时间的输出格式 , 函数返回一个存放时间的元组。
第二步:把表示时间的元组赋值给表示年、月、日的3个变量。
第三步:把表示年、月、日的3个变量传递给函数datetime ( ) ,进行第2次转换。
datetime ( year , month , day [ , hour [ ,minute [ , second [ , microsecond [ , tzinfo ] ] ] ] ]) 年、月、日3个参数必不可少。
import time,datetime
# 时间到字符串的转换
print time.strftime("%Y-%m-%d %X", time.localtime()) #输出:2015-06-02 22:38:55
# 字符串到时间的转换
t = time.strptime("2008-08-08", "%Y-%m-%d")
y, m, d = t[0:3]
print datetime.datetime(y, m, d)
注意:格式化日期的特殊标记是区分大小写的,%Y与%y 并不相同,具体含义参考上图。
6.2 正则表达式
正则表达式用于搜索、替换和解析字符串。使用正则表达式需要遵循一定的语法规则。Python中提供了re模块实现正则表达式的验证。
6.2.1 正则表达式简介
1、例:[ ok ] 将匹配包含 o 或 k 的字符。同时,[ 0-9a-zA-Z_ ] 等价于 \ w , [ ^ 0-9 ] 等价于 \D
如果对表达式一部分进行重复处理,要用到 限定符。
2、例:* 可以对正则表达式的某个部分重复匹配多次,这种匹配符号称之为限定符。
3、利用 { } 可以控制字符重复的次数。例:\ d {1 ,4 } 表示 1 位到 3 位数字。
匹配电话号码可以写成:[ \ ( ] ? \ d { 3 } [ \ ] - ) ? \ d {8} | [ \ ( ] ? \d {4} [ \ ] - ] ? \d {7} 其中:[ \ ( - ] ? 表示最多只能取 ( 或 - 其中之一 , | 表示 或
4、如果要对正则表达式进行嵌套,就需要使用分组 ”( )“ 。例:对3位数字重复3次: ( \d \d \d ) {2} ,如果对字符串 ”123456789“进行匹配,则匹配到的子串"123456"。 如果正则表达式写为 \d\d\d {2} ,则匹配结果为:”1234“ 和 ”5678“。 因为不带括号的表达式相当于 \d\d\d\d
5、正则表达式的每个分组会自动拥有一个组号。从左往右第1个出现的圆括号为第1个分组,表示 为 "\ 1" 。组号可以用于重复匹配某个分组。例如:字符串”abc"重复两次可以表示为:(abc) \1 . 默认情况下,正则表达式匹配最长的字符串作为结果。但可以通过在限定符后面添加 ? 的方式,获取最短匹配的结果 。 例:对字符串 “abcabc" 进行匹配 a.* c 匹配结果为最长匹配 'abcabc",如果是 a. * ? c 则匹配结果为 ”abc“ 和 ” abc" 。
6.2.2 使用 sys.re 模块处理正则表达式
# ^与$的使用
s = "HELLO WORLD"
print re.findall(r"^hello", s) # 输出:[]
print re.findall(r"^hello", s, re.IGNORECASE) #输出:['HELLO']
print re.findall("WORLD$", s) #输出:['WORLD']
print re.findall(r"wORld$", s, re.I) <span style="font-family:Arial, Helvetica, sans-serif;"> #</span><span style="font-family: Arial, Helvetica, sans-serif;">输出:['WORLD']</span><span style="font-family:Arial, Helvetica, sans-serif;">
</span>print re.findall(r"\b\w+\b", s) #输出: ['HELLO', 'WORLD']
replace ( ) 与re 模块的sub ( ) 同样可以实现字符串的替换功能。
import re
s = "hello world"
print re.sub("hello", "hi", s) #输出: hi world
print re.sub("hello", "hi", s[-4:]) #输出: orld 在字符串“orld“中替换”hello“。由于没有找到匹配的子串,所以sub()返回s[ -4:]
print re.sub("world", "China", s[-5:]) #输出:China 把world 替换成 China
注意:sub ( ) 先创建变量s的拷贝,然后在拷贝中替换字符串,并不会改变变量S的内容。
# 特殊字符的使用
s = "你好 WORLD2"
print "匹配字母数字:" + re.sub(r"\w", "hi", s)
print "替换次数:" + str(re.subn(r"\w", "hi", s)[1])
print "匹配非字母数字的字符:" + re.sub(r"\W", "hi", s)
print "替换次数:" + str(re.subn(r"\W", "hi", s)[1])
print "匹配空白字符:" + re.sub(r"\s", "*", s)
print "替换次数:" + str(re.subn(r"\s", "*", s)[1])
print "匹配非空白字符:" + re.sub(r"\S", "hi", s)
print "替换次数:" + str(re.subn(r"\S", "hi", s) [1])
print "匹配数字:" + re.sub(r"\d", "2.0", s)
print "替换次数:" + str(re.subn(r"\d", "2.0", s)[1])
print "匹配非数字:" + re.sub(r"\D", "hi", s)
print "替换次数:" + str(re.subn(r"\D", "hi", s)[1])
print "匹配任意字符:" + re.sub(r".", "hi", s)
print "替换次数:" + str(re.subn(r".", "hi", s)[1])
输出结果:
匹配字母数字:你好 hihihihihihi
替换次数:6
匹配非字母数字的字符:hihihihihiWORLD2
替换次数:5
匹配空白字符:你好*WORLD2
替换次数:1
匹配非空白字符:hihihihi hihihihihihi
替换次数:10
匹配数字:你好 WORLD2.0
替换次数:1
匹配非数字:hihihihihihihihihihi2
替换次数:10
匹配任意字符:hihihihihihihihihihihi
替换次数:11
# 限定符的使用
tel1 = "0791-1234567"
print re.findall(r"\d{3}-\d{8}|\d{4}-\d{7}", tel1) #输出:['0791-1234567'] ,匹配区号为3位的8位数电话码或区号为4位的7位数电话吧码。
tel2 = "010-12345678"
print re.findall(r"\d{3}-\d{8}|\d{4}-\d{7}", tel2) #输出:['010-12345678']
tel3 = "(010)12345678"
print re.findall(r"[\(]?\d{3}[\)-]?\d{8}|[\(]?\d{4}[\)-]?\d{7}", tel3) #输出:['(010)12345678']
print re.findall(r"a.*?c", "abcabc") #输出:['abc', 'abc']
# compile()预编译 在1个字符串中查找多个数字 ,使用compile ( ) 函数可以提高查找效率。
s = "1abc23def45"
p = re.compile(r"\d+") #返回1个正则表达式对象P,匹配变量s中的数字。
print p.findall(s) #输出:['1', '23', '45']
print p.pattern #输出当前使用的正则表达式 :\d+
# 分组
p = re.compile(r"(abc)\1") #定义一个分组 (abc) 函数返回1 个包含2个分组的正则表达式对象p
m = p.match("abcabcabc") #对字符串 进行搜索 ,返回1个match对象m
print m.group(0) #匹配整个表达式 输出结果:abcabc
print m.group(1) #返回第1次匹配成功的结果 :abc
print m.group() #默认为0 输出:abcabc
p = re.compile(r"(?P<one>abc)(?P=one)") #给分组命名 one
m = p.search("abcabcabc")
print m.group(0) #输出分组one的结果 :abc
print m.group("one") #获取正则表达式中分组的名称:['one']
print m.groupdict().keys() #获取正则表达式分组中的内容:['abc']
print m.groupdict().values() #获取当前正在使用的正则表达式。 输出结果:(?P<one>abc)(?P = one )