python编程学习——第四周

第四周

python学习笔记和做的一些习题 (python编程快速上手——让繁琐工作自动化)

第七章节

贪心和非贪心匹配

Python 的正则表达式默认是“贪心”的,这表示在有二义的情况下,它们会尽
可能匹配最长的字符串。花括号的“非贪心”版本匹配尽可能最短的字符串,即在结束的花括号后跟着一个问号。
在这里插入图片描述
注:问号在正则表达式中可能有两个含义:声明非贪心匹配、表示可选的分组。

findall()方法

除了search方法外,Regex对象也有一个findall()方法。
== search()方法与findall()方法的区别==:search()将返回一个Match
对象,包含被查找字符串中的“第一次”匹配的文本,而 findall()方法将返回一组字符串,包含被查找字符串中的所有匹配。而且如果正则表达式中没有分组,findall()不是返回一个 Match 对象,而是返回一个字符串列表。
在这里插入图片描述

字符分类

常用字符分类的缩写代码:

缩写字符分类表示
\d0到9的任何数字
\D除0到9的数字以外的任何字符
\w任何字母、数字或下划线字符(可以认为是匹配“单词”字符)
\W除字母、数字和下划线以外的任何字符
\s空格、制表符或换行符(可以认为是匹配“空白”字符)
\S除空格、制表符和换行符以外的任何字符

在这里插入图片描述
其中:
在这里插入图片描述
创建自己的字符分类:
可以用方括号定义自己的字符分类,也可以使用短横表示字母或数字的范围,通过在字符分类的左方括号后加上一个插入字符(^),就可以得到“非字符类”,非字符类将匹配不在这个字符类中的所有字符。
在这里插入图片描述

插入字符和美元字符

可以在正则表达式的开始处使用插入符号(^),表明匹配必须发生在被查找文本开始处。
可以在正则表达式的末尾加上美元符号($),表示该字符串必须以这个正则表达式的模式结束。
若这两个符号同时使用,表明整个字符串必须匹配该模式。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

通配字符

.(句点)字符称为“通配符”。它匹配除了换行之外的所有字符,他只能匹配一个字符。
在这里插入图片描述

正则表达式符号总结
  • ?匹配零次或一次前面的分组。
  • *匹配零次或多次前面的分组。
  • +匹配一次或多次前面的分组。
  • {n}匹配 n 次前面的分组。
  • {n,}匹配 n 次或更多前面的分组。
  • {,m}匹配零次到 m 次前面的分组。
  • {n,m}匹配至少 n 次、至多 m 次前面的分组。
  • {n,m}?或*?或+?对前面的分组进行非贪心匹配。
  • ^spam 意味着字符串必须以 spam 开始。
  • spam$意味着字符串必须以 spam 结束。
  • .匹配所有字符,换行符除外。
  • \d、\w 和\s 分别匹配数字、单词和空格。
  • \D、\W 和\S 分别匹配出数字、单词和空格外的所有字符。
  • [abc]匹配方括号内的任意字符(诸如 a、b 或 c)。
  • [^abc]匹配不在方括号内的任意字符。
不区分大小写的匹配

通常来讲,正则表达式用你指定的大小写匹配文本,但是,有时候你只关心匹配字母,不关心它们是大写或小写。要让正则表达式不区分大小写,可以向 re.compile()传入 re.IGNORECASE 或 re.I,作为第二个参数。
在这里插入图片描述

用sub()方法替换字符串

Regex对象的 sub()方法需要传入两个参数。第一个参数是一个字符串,用于取代发现的匹配。第二个参数是一个字符串,即正则表达式。sub()方法返回替换完成后的字符串。
在这里插入图片描述

管理复杂的正则表达式

匹配复杂的文本模式,可能需要长的、费解的正则表达式。你可以告诉 re.compile(),忽略正则表达式字符串中的空白符和注释,从而缓解这一点。要实现这种详细模式,可以向 re.compile()传入变量 re.VERBOSE,作为第二个参数。

phoneRegex = re.compile(r'''(
 (\d{3}|\(\d{3}\))?                            # 区号
 (\s|-|\.)?                                    # 分隔符
 (\d{3})                                         # 前3位数字
 (\s|-|\.)                                     # 分隔符
 (\d{4})                                         # 后4位数字
 (\s*(ext|x|ext.)\s*\d{2,5})?                  # 扩展名
 )''', re.VERBOSE)

组合使用re.IGNORECASE、re.DOTALL和re.VERBOSE:
如果要同时使用re.VERBOSE、re.IGNOREC ASE,可以使用管道字符(|)将变量组合起来,这样就不受re.compile()函数只接收一个值作为第二个参数的限制。管道字符在这里称为“按位或”操作符。

项目:电话号码和E-mail地址提取程序
import re,pyperclip
#为电话号码写一个正则表达式
phoneRegex = re.compile(r'''(
 (\d{3})                           
 (\s|-|\.)?                                    
 (\d{3})                                         
 (\s|-|\.)                                     
 (\d{4})                                         
 (\s*(ext|x|ext.)\s*\d{2,5})?                  
 )''', re.VERBOSE)

#为E-mail地址创建一个正则表达式
emailRegex = re.compile(r'''(            
    [a-zA-Z0-9._%+-]+                           
    @                                          
    [a-zA-Z0-9.-]+                              
    (\.[a-zA-Z]{2,4})                          
    )''',re.VERBOSE )

#在剪贴文本中找到所有匹配
text = str(pyperclip.paste())
matches = []
for groups in phoneRegex.findall(text):
    phoneNum = '-'.join([groups[1],groups[3],groups[5]])
#不知道书上下面两句是什么意思   
#   if groups[8] != ' ':
#      phoneNum += ' x' + groups[8]
    matches.append(phoneNum)
for groups in emailRegex.findall(text):
    matches.append(groups[0])

# 所有匹配连接成一个字符串,复制到剪贴板
if len(matches) > 0:
    pyperclip.copy('\n'.join(matches))
    print('复制到剪贴板:')
    print('\n'.join(matches))
else:
    print('没有找到电话号码和邮箱')

第七章节习题

1.创建 Regex 对象的函数是什么?
re.compile()函数。

2.在创建 Regex 对象时,为什么常用原始字符串?
使用原始字符串是为了让反斜杠不必转义。

3.search()方法返回什么?
Match对象。

4.通过 Match 对象,如何得到匹配该模式的实际字符串?
group()方法返回匹配文本的字符串。

5.用 r’(\d\d\d)-(\d\d\d-\d\d\d\d)'创建的正则表达式中,分组 0 表示什么?分组 1呢?分组 2 呢?
分组0表示整个匹配,分组1包含第一组括号,分组2包含第二组括号。

6.括号和句点在正则表达式语法中有特殊的含义。如何指定正则表达式匹配真正的括号和句点字符?
句号和括号可以用反斜杠转义:.、(和) 。

7.findall()方法返回一个字符串的列表,或字符串元组的列表。是什么决定它提供哪种返回?
如果正则表达式没有分组,就返回字符串的列表。如果正则表达式有分组,就返回字符串元组的列表。

8.在正则表达式中,|字符表示什么意思?
表示匹配符号左右两边任意一个。

9.在正则表达式中,?字符有哪两种含义?
?字符可以表示"匹配前面分组0次或1次",或用于表示非贪婪匹配。

10.在正则表达式中,+和*字符之间的区别是什么?
+匹配1次或多次。*匹配0次或多次。

11.在正则表达式中,{3}和{3,5}之间的区别是什么?
{3}精确匹配前面分组的3次实例。{3,5}匹配3至5次实例。
比如(Ha){3}表示HaHaHa
(Ha){3,5}表示HaHaHa或HaHaHaHa或HaHaHaHaHa

12.在正则表达式中,\d、\w 和\s 缩写字符类是什么意思?
数字、单词和空白字符。

13.在正则表达式中,\D、\W 和\S 缩写字符类是什么意思?
分别匹配一个字符,它不是数字、单词或空白字符。

14.如何让正则表达式不区分大小写?
将re.I 或者 re.IGNORECASE作为第二个参数传入re.compile(),让匹配不区分大小写。

15.字符.通常匹配什么?如果 re.DOTALL 作为第二个参数传递给re.compile(),它会匹配什么?
字符.通常匹配任何字符,换行符除外。

16..* 和 *?之间的区别是什么?
.表示贪婪匹配,.?表示非贪婪匹配。

17.匹配所有数字和小写字母的字符分类语法是什么?
[0-9a-z]或[a-z0-9]

18.如果 numRegex = re.compile(r’\d+’),那么 numRegex.sub(‘X’, ‘12 drummers, 11 pipers, five rings, 3 hens’)返回什么?
‘X drummers,X pipers,five rings,X hens’

19.将 re.VERBOSE 作为第二个参数传递给 re.compile(),让你能做什么?
添加空格和注释

20.如何写一个正则表达式,匹配每 3 位就有一个逗号的数字?它必须匹配以下数字:

  • ‘42’
  • ‘1,234’
  • ‘6,368,745’
    但不会匹配:
  • ‘12,34,567’ (逗号之间只有两位数字)
  • ‘1234’ (缺少逗号)

参考链接https://blog.csdn.net/daaa2019/article/details/102963975

import re
threeNumRegex = re.compile(r'''
    (?:(?<![\d|\,])\d{1,3}(?=\s)) #匹配只有1-3位数,左边
    |
    (?<![\d|\,])(?:\d{1,3})(?:\,\d{3})+(?=\s) #匹配带有","的情况
''', re.VERBOSE)
text = '''
    42
    1,234
    6,368,745
    1234
    12,34,567
'''
result = threeNumRegex.findall(text)
print(result)

在这里插入图片描述

21.如何写一个正则表达式,匹配姓 Nakamoto 的完整姓名?你可以假定名字总是出现在姓前面,是一个大写字母开头的单词。该正则表达式必须匹配:

  • ‘Satoshi Nakamoto’
  • ‘Alice Nakamoto’
  • ‘RoboCop Nakamoto’
    但不匹配:
  • ‘satoshi Nakamoto’(名字没有大写首字母)
  • ‘Mr. Nakamoto’(前面的单词包含非字母字符)
  • ‘Nakamoto’ (没有名字)
  • ‘Satoshi nakamoto’(姓没有首字母大写)
import re
nameRegex = re.compile(r'[A-Z][a-zA-Z]*\sNakamoto')
text = '''
    Satoshi Nakamoto 
    Alice Nakamoto
    RoboCop Nakamoto
    satoshi Nakamoto
    Mr. Nakamoto
    Nakamoto 
    Satoshi nakamoto
'''
result = nameRegex.findall(text)
print(result)

在这里插入图片描述

22.如何编写一个正则表达式匹配一个句子,它的第一个词是 Alice、Bob 或Carol,第二个词是 eats、pets 或 throws,第三个词是 apples、cats 或 baseballs。该句子以句点结束。这个正则表达式应该不区分大小写。它必须匹配:

  • ‘Alice eats apples.’
  • ‘Bob pets cats.’
  • ‘Carol throws baseballs.’
  • ‘Alice throws Apples.’
  • ‘BOB EATS CATS.’
    但不匹配:
  • ‘RoboCop eats apples.’
  • ‘ALICE THROWS FOOTBALLS.’
  • ‘Carol eats 7 cats.’
import re
senRegex = re.compile(r'(Alice|Bob|Carol)\s(eats|pets|throws)\s(apples|cats|baseablls)\.',re.I)

text = '''
   'Alice eats apples. '
   'Bob pets cats.' 
   'Carol throws baseballs.' 
   'Alice throws Apples.' 
   'BOB EATS CATS.' 
   'RoboCop eats apples.'
   'ALICE THROWS FOOTBALLS.'
   'Carol eats 7 cats.' 
'''
result = senRegex.findall(text)
print(''.join(text))

这里还有一点问题,因为输出的不是预期中的句子
在这里插入图片描述

第七章实践项目

强口令检测

写一个函数,它使用正则表达式,确保传入的口令字符串是强口令。强口令的定义是:长度不少于 8 个字符,同时包含大写和小写字符,至少有一位数字。你可能需要用多个正则表达式来测试该字符串,以保证它的强度。

import  re
print("强口令要求:字符串长度不少于8个,同时包含大小写,且至少含有一位数字。")
strongStr = input("请输入一个强口令:")


def strongPassword(str): #定义正则表达式函数
    lengthRex1 = re.compile(r'[a-zA-Z0-9]{8,}')
    lengthRex2 = re.compile(r'[A-Z]+')
    lengthRex3 = re.compile(r'[a-z]+')
    lengthRex4 = re.compile(r'[0-9]+') 
    if lengthRex1.search(strongStr) != None:
        print('长度8以上')
        if lengthRex2.search(strongStr) != None:
            print('有大写')
            if lengthRex3.search(strongStr) != None:
               print('有小写')
               if lengthRex4.search(strongStr) != None:
                  print('有数字')
                  print(lengthRex1.search(strongStr))
                  return True
               else:
                   print('没有数字')
                   return False                 
            else:
                print('没有小写')
                return False
                
        else:
            print('没有大写')
            return False
    else:
        print('长度不够8,或者有其他字符')
        return False
    
 
while strongPassword(strongStr) == False: #判断函数返回值是否为False,循环调用函数strongPassword()
    print('口令强度不够!请重新输入:')
    strongStr = input() #重新输入更新字符变量
    strongPassword(strongStr)#再次调用函数
else:
    print('Nice!强口令强度足够,可以使用!')

这里不知道为啥一个强口令会重复判断两次
在这里插入图片描述

strip()的正则表达式版本

写一个函数,它接受一个字符串,做的事情和 strip()字符串方法一样。如果只传入了要去除的字符串,没有其他参数,那么就从该字符串首尾去除空白字符。否则,函数第二个参数指定的字符将从该字符串中去除。
这个题没有看太明白,参考了链接:https://blog.csdn.net/dongyu1703/article/details/81782081

import re
 
def REstrip(text, param=' '):
	mo = re.compile(r'^([' + str(param) + r']*)(.*?)([' + str(param) + ']*)$')
	result = mo.search(text)
	if (result != None):
		print(result.group(2))
 
 
text = input("Please input the text: ")
param = input("Please input the param: ")
REstrip(text, param)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值