Python11-正则表达式

Python11-正则表达式

    • 1.正则表达式简介
    • 2.正则表达式常见用法和符号
    • 3.正则查找
    • 4.re.Match对象与group
    • 5.re.compile
    • 6.正则表达式修饰符
    • 7.正则匹配规则
    • 8.正则表达式匹配练习
    • 9.正则替换
    • 10.贪婪模式和非贪婪模式


1.正则表达式简介

正则表达式(Regular Expression)是一种用于匹配、查找和操作文本的工具。它是由一系列字符和特殊字符组成的模式,用于描述字符串的特征。

在Python中,可以使用内置的re模块来使用正则表达式。re模块提供了一系列函数来进行正则表达式的匹配、查找和替换等操作。

Q:将下面的word中的数字取出

word = 'a1b23c456def789'number = ''
numbers = []
for i, w in enumerate(word):if '0' <= w <= '9':number += wif i == len(word) - 1:numbers.append(number)else:if number != '':numbers.append(number)number = ''
print(numbers)

使用正则表达式写法:

import reword = 'a1b23c456def789'print(re.findall(r'\d+', word))  # ['1', '23', '456', '789']
print(re.sub(r'\d', 'x', word))  # axbxxcxxxdefxxx
print(re.sub(r'\d+', 'x', word))  # axbxcxdefx

通过上面的例子我们体会到了使用正则表达式对字符串处理的便捷。下面我们将介绍python中正则表达式的使用

2.正则表达式常见用法和符号

  1. 匹配字符:
    • 普通字符:可以直接匹配文本中的普通字符,例如 a 匹配字符 “a”。
    • 字符类:用方括号 [] 表示,可以匹配方括号内的任意一个字符。例如 [aeiou] 可以匹配任何一个元音字母。
    • 范围类:在字符类中使用连字符 - 表示一个范围。例如 [0-9] 可以匹配任意一个数字。
    • 预定义字符类:有一些预定义的字符类,例如 \d 匹配任意一个数字,\w 匹配任意一个字母、数字或下划线,\s 匹配任意一个空白字符。
    • 否定字符类:在字符类的开头使用 ^ 表示否定,例如 [^0-9] 匹配任意一个非数字字符。
  2. 匹配重复:
    • *:匹配前面的元素零次或多次。
    • +:匹配前面的元素一次或多次。
    • ?:匹配前面的元素零次或一次。
    • {n}:匹配前面的元素恰好 n 次。
    • {n,}:匹配前面的元素至少 n 次。
    • {n,m}:匹配前面的元素至少 n 次且不超过 m 次。
  3. 匹配位置:
    • ^:匹配输入字符串的开始位置。
    • $:匹配输入字符串的结束位置。
    • \b:匹配单词的边界。
  4. 特殊字符:
    • \:转义字符,用于转义特殊字符。
    • .:匹配除换行符外的任意字符。
    • |:匹配两个或多个表达式之一。

对上面常见的符号有个印象,下面会使用到。

3.正则查找

python里的正则查找有以下几个方法:search、match、fullmatch、findall、finditer

search使用:用于在字符串中搜索匹配某个模式的子串。

re.search(pattern, string, flags=0)
'''
pattern:要匹配的正则表达式模式。
string:要搜索的字符串。
flags(可选):用于控制正则表达式的匹配方式的标志。
'''

\d:表示任意一个数字
+:匹配前面的元素一次或多次,\d+就是前面的数字出现一次或多次
?:匹配前面的元素零次或一次

import reword = 'afd1456b23c32567def346'# 3开头的数字
result = re.search(r'3\d+', word)
print(result)  # <re.Match object; span=(11, 16), match='32567'>result = re.search(r'3\d', word)
print(result)  # <re.Match object; span=(11, 13), match='32'>result = re.search(r'3\d?', word)
print(result)  # <re.Match object; span=(9, 10), match='3'>

需要注意的是,re.search()只会返回第一个匹配的子串。如果需要找到所有匹配的子串,可以使用re.findall()函数。


match使用:用于从字符串的开头开始匹配某个模式。

re.match(pattern, string, flags=0)
'''
pattern:要匹配的正则表达式模式。
string:要匹配的字符串。
flags(可选):用于控制正则表达式的匹配方式的标志。
'''
import reword = 'afd1456b23c32567def346'# match:从字符串的开头匹配
result = re.match(r'3\d+', word)
print(result)  # None# a后面没有数字
result = re.match(r'a\d+', word)
print(result)  # None# afd后面有数字,+表示一个或多个
result = re.match(r'afd\d+', word)
print(result)  # <re.Match object; span=(0, 7), match='afd1456'>

需要注意的是,re.match()只会从字符串的开头进行匹配。如果需要在整个字符串中查找匹配的子串,可以使用re.search()函数或re.findall()函数。


fullmatch使用:用于检查整个字符串是否与给定的模式完全匹配

re.fullmatch(pattern, string, flags=0)
'''
pattern:要匹配的正则表达式模式。
string:要匹配的字符串。
flags(可选):用于控制正则表达式的匹配方式的标志。
'''

它要求模式与字符串完全一致,即从字符串的开头到结尾都需要匹配。

import reword = 'afd1456b23c32567def346'# 不匹配:afd开头,后面是整个数字
result = re.fullmatch(r'afd\d+', word)
print(result)  # Noneword1 = 'afd2333'
result = re.fullmatch(r'afd\d+', word1)
print(result)  # <re.Match object; span=(0, 7), match='afd2333'>

search、match、fullmatch匹配到的结果都是一个 re.Match 类型的对象。


finditer使用:用于在字符串中查找所有匹配某个模式的子串,并返回一个迭代器(Iterator),每个迭代项都是一个匹配对象。

re.finditer(pattern, string, flags=0)
'''
pattern:要匹配的正则表达式模式。
string:要搜索的字符串。
flags(可选):用于控制正则表达式的匹配方式的标志。
'''

re.finditer()函数可以方便地获取所有匹配的子串,适用于需要遍历并处理多个匹配结果的情况。

import reword = 'afd1456b23c32567def346'# 将字符串里所有匹配到的结果查询到,得到的结果是一个迭代器
# 得到的迭代器里的每个元素,又是一个 re.Match 类型的对象
result = re.finditer(r'3\d+', word)
print(result)  # <re.Match object; span=(11, 16), match='32567'>for i in result:print(i)

findall使用:用于在字符串中查找所有匹配某个模式的子串,并返回一个包含所有匹配结果的列表。

re.findall(pattern, string, flags=0)
'''
pattern:要匹配的正则表达式模式。
string:要搜索的字符串。
flags(可选):用于控制正则表达式的匹配方式的标志。
'''
import reword = 'afd1456b23c32567def346'# 匹配到的结果字符串放在列表中返回
result = re.findall(r'3\d+', word)
print(result)  # ['32567', '346']

需要注意的是,re.findall()函数只返回匹配结果的内容,而不包含其他关于匹配位置等的信息。如果需要更详细的匹配信息,可以使用re.finditer()函数。

4.re.Match对象与group

当使用re模块的函数进行匹配操作时,如果匹配成功,就会返回一个re.Match对象,该对象包含关于匹配结果的信息。search、match、fullmatch、finditer匹配到的结果都有 re.Match 类型的对象。

查看re.Match对象的成员与方法:

import reword = 'afd1456b23c32567def346'result = re.search(r'3\d+', word)
print(dir(result))

输出如下:

['__class__', '__copy__', '__deepcopy__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'end', 'endpos', 'expand', 'group', 'groupdict', 'groups', 'lastgroup', 'lastindex', 'pos', 're', 'regs', 'span', 'start', 'string']

span()、string、group()

import reword = 'afd1456b23c32567def346'# 匹配到的结果字符串放在列表中返回
result = re.search(r'3\d+', word)
print(result)  # <re.Match object; span=(11, 16), match='32567'># print(dir(result))# 得到匹配到的字符串的开始和结束,左闭右开
print(result.span(), word[result.span()[0]:result.span()[1]])  # (11, 16) 32567# 查找的完整的字符串
print(result.string)  # afd1456b23c32567def346# 使用group获取匹配到的结果字符串
print(result.group())  # 32567

re.Match对象的group():方法用于返回匹配的子串内容。

group()方法可以接受一个可选的参数group_num,用于指定要返回的分组号。如果未提供group_num参数,则默认返回整个匹配的子串。

import reword = 'a10b2453c5896d717e123'result = re.search(r'b\d+c\d+d\d+', word)
print(result)  # <re.Match object; span=(3, 17), match='b2453c5896d717'>
print(result.group())  # b2453c5896d717

使用小括号进行分组

import reword = 'a10b2453c5896d717e123'# r'(b\d+)(c\d+)(d\d+)' 有4个分组
# 第0组是整体,其余3个括号是另外三个分组
result = re.search(r'(b\d+)(c\d+)(d\d+)', word)
print(result)  # <re.Match object; span=(3, 17), match='b2453c5896d717'>
print(result.group())  # b2453c5896d717# 第0组是整体
print(result.group(0))  # b2453c5896d717
print(result.group(1))  # b2453
print(result.group(2))  # c5896
print(result.group(3))  # d717

groups()方法:返回所有分组匹配的子串内容,一个包含所有分组匹配结果的元组。

import reword = 'a10b2453c5896d717e123'print(result.groups())  # ('b2453', 'c5896', 'd717')# groupdict以字典形式保存有组名的分组数据
# (?P<group_name>) 用来设置组名
result = re.search(r'(?P<group_name>b\d+)(c\d+)(d\d+)', word)
print(result.groupdict())  # {'group_name': 'b2453'}

groupdict()方法:返回具名分组匹配的子串内容。

如果正则表达式模式中使用了具名分组,即通过(?P<name>pattern)语法指定了分组的名称,groupdict()方法将返回一个字典,其中键是分组的名称,值是匹配的子串内容。

import reword = 'a10b2453c5896d717e123'# groupdict以字典形式保存有组名的分组数据
# (?P<group_name>) 用来设置组名
result = re.search(r'(?P<group_name>b\d+)(c\d+)(d\d+)', word)
print(result.groupdict())  # {'group_name': 'b2453'}

5.re.compile

re.compile() 方法用于将正则表达式模式编译为一个可重复使用的正则表达式对象。

re.compile(pattern, flags=0)
  • pattern:要编译的正则表达式模式。
  • flags(可选):用于控制正则表达式的匹配方式的标志。

re.compile()方法的优点在于,当需要多次使用同一个正则表达式模式时,可以先编译为正则表达式对象,然后重复使用该对象进行匹配,避免了每次使用都要重新编译模式的性能开销。

import reword = 'ab322wm234dasdd'pattern = re.compile(r'm\d+')
print(pattern.search(word))  # <re.Match object; span=(6, 10), match='m234'>

6.正则表达式修饰符

正则修饰符是对正则规则进行修饰,让正则含有不同含义。使用修饰符(也称为标志或选项)来控制正则表达式的匹配方式。修饰符在re模块的函数中作为可选参数传递。

下面是常用的修饰符:

  • re.I(或re.IGNORECASE):忽略大小写匹配。
  • re.M(或re.MULTILINE):多行模式,使^$匹配每行的开头和结尾。
  • re.S(或re.DOTALL):点(.)匹配包括换行符在内的所有字符。
  • re.X(或re.VERBOSE):详细模式,忽略空白和注释,可以使用多行模式。

这些修饰符可以单独使用,也可以使用位运算符|进行组合。

import reword = 'ab322wm234Qasdd'print(re.search(r'q', word))  # None# re.I 忽略大小写
print(re.search(r'q', word, re.IGNORECASE))  # <re.Match object; span=(10, 11), match='Q'>

.表示除了\n以外的任意字符

import reword = 'a\n1_*/({+'
# .表示除了\n以外的任意字符
print(re.findall(r'.', word))  # ['a', '1', '_', '*', '/', '(', '{', '+']
# re.S匹配包括换行在内的所有字符
print(re.findall(r'.', word, re.S))  # ['a', '\n', '1', '_', '*', '/', '(', '{', '+']

7.正则匹配规则

总的原则:

1.数字和字母表示它本身,没有特殊含义

2.\反斜杠有特殊含义,用来做转义。大多数字母前面加\反斜杠以后会有不同含义。

3.标点符号只有被转义时才匹配自身,否则它们表示特殊的含义。

4.反斜杠本身需要使用反斜杠转义。由于正则表达式通常都包含反斜杠,所以最好使用原始字符串来表示它们。模式元素(如 r’\t’,等价于\\t )匹配相应的特殊字符。


非打印字符也可以是正则表达式的组成部分。下表列出了表示非打印字符的转义序列:

字符描述
\cx匹配由x指明的控制字符。例如, \cM 匹配一个 Control-M 或回车符。x 的值必须为 A-Z 或 a-z 之一。否则,将 c 视为一个原义的 ‘c’ 字符。
\f匹配一个换页符。等价于 \x0c\cL
\n匹配一个换行符。等价于 \x0a\cJ
\r匹配一个回车符。等价于 \x0d\cM
\s匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]。注意 Unicode 正则表达式会匹配全角空格符。
\S(大写S)匹配任何非空白字符。等价于 [^\f\n\r\t\v]
\t匹配一个制表符。等价于 \x09\cI
\v匹配一个垂直制表符。等价于 \x0b\cK

需要记住:\r \n \t\s \S


特殊字符是一些有特殊含义的字符。若要匹配这些特殊字符,必须首先使字符"转义",即,将反斜杠字符\ 放在它们前面。下表列出了正则表达式中的特殊字符:

特殊字符描述
( )标记一个子表达式的开始和结束位置。子表达式可以获取供以后使用。要匹配这些字符,请使用 \( 和 \)。
.匹配除换行符 \n 之外的任何单字符。要匹配 . ,请使用 \.
[标记一个中括号表达式的开始。要匹配 [,请使用 \[
\将下一个字符标记为或特殊字符、或原义字符、或向后引用、或八进制转义符。例如, ‘n’ 匹配字符 ‘n’。‘\n’ 匹配换行符, \\ 匹配 \,而 \( 则匹配 ( 。
{标记限定符表达式的开始。要匹配 {,请使用 \{
``
\d匹配一个数字字符。等价于 [0-9]。
[0-9]匹配任何数字。等价于 \d
\D匹配一个非数字字符。等价于 [^0-9]
[a-z]匹配任何小写字母
[A-Z]匹配任何大写字母
[a-zA-Z0-9]匹配任何字母及数字。等价于\w
\w匹配包括下划线的任何单词字符。等价于[A-Za-z0-9_]
\W(大写W)匹配任何非单词字符。等价于 [^A-Za-z0-9_]
[\u4e00-\u9fa5]匹配纯中文

需要记住:\d\D\w\W


定位符能够将正则表达式固定到行首或行尾。它们还能够创建这样的正则表达式,这些正则表达式出现在一个单词内、在一个单词的开头或者一个单词的结尾。

定位符用来描述字符串或单词的边界,^$ 分别指字符串的开始与结束,\b 描述单词的前或后边界,\B 表示非单词边界。

正则表达式的定位符有:

特殊字符描述
^匹配输入字符串的开始位置,例如:^h匹配以h开头;在方括号表达式中时,它表示不接受该字符集合,例如[^0-9]匹配除了数字以外的数据。要匹配 ^ 字符本身,请使用 \^
$匹配输入字符串的结尾位置。要匹配 $ 字符本身,请使用 \$
\b匹配一个单词边界,即字与空格间的位置。
\B非单词边界匹配。

限定符用来指定正则表达式的一个给定组件必须要出现多少次才能满足匹配。有 ***** 或 +?{n}{n,}{n,m} 共6种。

正则表达式的限定符有:

字符描述
*匹配前面的子表达式零次或多次。例如,zo* 能匹配 z 以及 zoo。 等价于{0,}
+匹配前面的子表达式一次或多次。例如,zo+ 能匹配 zo 以及 zoo,但不能匹配 z。+ 等价于 {1,}。
?匹配前面的子表达式零次或一次。例如,do(es)? 可以匹配 dodoes 中的 doesdoxy 中的 do? 等价于 {0,1}
{n}n 是一个非负整数。匹配确定的 n 次。例如,o{2} 不能匹配 Bob 中的 o,但是能匹配 food 中的两个 o
{n,}n 是一个非负整数。至少匹配n 次。例如,o{2,} 不能匹配 Bob 中的 o,但能匹配 foooood 中的所有 oo{1,} 等价于 o+o{0,} 则等价于 o*
{n,m}m 和 n 均为非负整数,其中n <= m。最少匹配 n 次且最多匹配 m 次。请注意在逗号和两个数之间不能有空格。

示例:

import rere.search(r'\s', '大家好 我是 代码')  # 匹配所有的空字符
re.search(r'\S', '大家')  # 匹配所有的非空字符
re.search(r'\n', '大家好\n我是代码')  # 匹配换行
re.search(r'n$', 'hello python')  # 匹配以 n 结尾
re.search(r'^h.+n$', 'hello python')  # 匹配以 h 开头,中间出现一次或多次任意字符,并且以n结尾
re.search(r'^ha*', 'h')  # 匹配以 h 开头,a出现0次或者一次

8.正则表达式匹配练习

Q1:用户名匹配:由数字、大小写字母、下划线_和中横线-组成,长度为4到14位,并且不能以数字开头。

import redef check_username(username):pattern = r'^[a-zA-Z_][a-zA-Z0-9_-]{3,13}$'match = re.match(pattern, username)if match:return Trueelse:return False# 测试用户名
usernames = ["user_123", "User-Name", "123abc", "_username", "user-name", "user_name_longer_than_14"]
for username in usernames:if check_username(username):print(f"{username}: 匹配")else:print(f"{username}: 不匹配")

正则表达式模式解释:

  • ^:匹配字符串的开头
  • [a-zA-Z_]:匹配一个字母、下划线或中横线(不能以数字开头)
  • [a-zA-Z0-9_-]{3,13}:匹配3到13个数字、大小写字母、下划线或中横线
  • $:匹配字符串的结尾

Q2:匹配邮箱

import redef check_email(email):pattern = r'^[\w\.-]+@[\w\.-]+\.\w+$'match = re.match(pattern, email)if match:return Trueelse:return False# 测试邮箱地址
emails = ["john.doe@example.com", "jane_123@gmail.com", "invalid_email", "user@example", "admin@domain"]
for email in emails:if check_email(email):print(f"{email}: 匹配")else:print(f"{email}: 不匹配")

正则表达式模式解释:

  • ^:匹配字符串的开头
  • [\w\.-]+:匹配一个或多个字母、数字、下划线、点号或中横线(邮箱用户名部分)
  • @:匹配邮箱地址中的@
  • [\w\.-]+:匹配一个或多个字母、数字、下划线、点号或中横线(邮箱域名部分)
  • \.:匹配邮箱地址中的点号
  • \w+:匹配一个或多个字母、数字或下划线(邮箱域名后缀)
  • $:匹配字符串的结尾

Q3:匹配手机号

import redef check_phone_number(phone_number):pattern = r'^1[3-9]\d{9}$'match = re.match(pattern, phone_number)if match:return Trueelse:return False# 测试手机号码
phone_numbers = ["13812345678", "15567891234", "12345678901", "189abcd1234", "01234567890"]
for phone_number in phone_numbers:if check_phone_number(phone_number):print(f"{phone_number}: 匹配")else:print(f"{phone_number}: 不匹配")

正则表达式模式解释:

  • ^:匹配字符串的开头
  • 1:匹配手机号码的开头必须是1
  • [3456789]:匹配3、4、5、6、7、8、9中的一个数字
  • \d{9}:匹配9个数字(手机号码的剩余部分)
  • $:匹配字符串的结尾

Q4:匹配身份证号。

import redef check_id_card(id_card):pattern = r'^[1-9]\d{16}(\d|X|x)$'match = re.match(pattern, id_card)if match:return Trueelse:return False# 测试身份证号码
id_cards = ["110101199003077934", "310110198706152518", "12345678901234567X", "123456789012345678", "A1234567890123456"]
for id_card in id_cards:if check_id_card(id_card):print(f"{id_card}: 匹配")else:print(f"{id_card}: 不匹配")

正则表达式模式解释:

  • ^:匹配字符串的开头
  • [1-9]:匹配1到9中的一个数字(身份证号码的开头不能为0)
  • \d{16}:匹配16个数字(身份证号码的剩余部分)
  • (\d|X|x):匹配一个数字或字母X(身份证号码的最后一位校验位)
  • $:匹配字符串的结尾

Q5:匹配URL地址

import redef check_url(url):pattern = r'^(http|https)://[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/?(\S+)?$'match = re.match(pattern, url)if match:return Trueelse:return False# 测试URL地址
urls = ["http://www.example.com", "https://www.example.com/path", "ftp://www.example.com", "www.example.com","http://example", "https://123.456.789"]
for url in urls:if check_url(url):print(f"{url}: 匹配")else:print(f"{url}: 不匹配")

正则表达式模式解释:

  • ^:匹配字符串的开头
  • (http|https):匹配http或https
  • ://:匹配://
  • [a-zA-Z0-9.-]+:匹配一个或多个字母、数字、点号或中横线(域名部分)
  • \.[a-zA-Z]{2,}:匹配一个点号后面跟着两个或更多字母(域名后缀部分)
  • /?(\S+)?:匹配可选的斜杠后面跟着一个或多个非空字符(路径部分)
  • $:匹配字符串的结尾

9.正则替换

re.sub() 是 Python 中用于替换字符串中的匹配项的函数。它使用正则表达式来查找匹配项,并使用提供的替换字符串来替换它们。re.sub() 函数的语法如下:

re.sub(pattern, repl, string, count=0, flags=0)

参数说明:

  • pattern:要匹配的正则表达式模式。
  • repl:用于替换匹配项的字符串或替换函数。
  • string:要进行替换的原始字符串。
  • count:可选参数,指定替换的最大次数。默认为 0,表示替换所有匹配项。
  • flags:可选参数,用于控制正则表达式的匹配方式,如 re.IGNORECASE(忽略大小写匹配)等。

re.sub() 函数的工作流程如下:

  1. 在原始字符串 string 中查找与正则表达式模式 pattern 匹配的部分。
  2. 对于每一个匹配项,将其替换为 repl 字符串或替换函数的结果。
  3. 返回替换后的字符串。

替换字符串中的匹配项

import retext = "Hello, World!"
new_text = re.sub(r"Hello", "Hi", text)print(new_text)  # Output: Hi, World!

换字符串中的多个匹配项

import retext = "Hello, Hello, Hello!"
new_text = re.sub(r"Hello", "Hi", text)print(new_text)  # Output: Hi, Hi, Hi!

使用替换函数

import redef to_uppercase(match):return match.group().upper()text = "hello, world!"
new_text = re.sub(r"\b\w+\b", to_uppercase, text)print(new_text)  # Output: HELLO, WORLD!

10.贪婪模式和非贪婪模式

贪婪模式和非贪婪模式是用于匹配字符串时的两种不同行为。它们涉及到量词(quantifier)的使用,量词用于指定匹配模式中重复出现的次数。

贪婪模式(Greedy Mode):
贪婪模式是正则表达式的默认行为,它会尽可能多地匹配字符串。当使用贪婪模式时,量词会匹配尽可能多的字符。例如,正则表达式 a.*b 匹配的是从第一个 a 到最后一个 b 之间的所有字符,尽管可能有多个 a 和多个 b 存在。

非贪婪模式(Non-Greedy Mode):
非贪婪模式使用 ? 后缀来指示量词变为非贪婪模式。它会尽可能少地匹配字符串。当使用非贪婪模式时,量词会匹配尽可能少的字符。例如,正则表达式 a.*?b 匹配的是从第一个 a 到最近的 b 之间的字符,只取最短的匹配结果。

下面通过示例来说明贪婪模式和非贪婪模式的区别:

import repattern = r'<.*>'
text = '<a> <b> <c>'result = re.match(pattern, text)
print(result.group())  # <a> <b> <c>

输出结果为<a> <b> <c>。在这个例子中,正则表达式<.*>使用了贪婪模式,它尝试匹配从第一个<到最后一个>之间的所有字符,包括多个标签。

在Python正则表达式中,可以使用?符号来表示非贪婪模式。

import repattern = r'<.*?>'
text = '<a> <b> <c>'result = re.match(pattern, text)
print(result.group())  # <a>

这个正则表达式<.*?>使用了非贪婪模式,?表示在*后面加上?表示非贪婪匹配。非贪婪模式尽量匹配最短的可能字符串,所以它只匹配到了第一个>之前的字符。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/118742.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JS-文件下载,实现在ios也是下载 而不是预览,

需求 通过A链接的方式&#xff0c;把从后台获取到的文件下载到本地&#xff0c;实现在移动端,PC端都能下载 问题 通过ajax请求后端生成的文件流之后&#xff0c;创建BLOB文件进行下载&#xff0c;在PC端和移动安卓端都可以实现下载到本地和对应的手机&#xff0c;而在IOS端的…

开源思维导图白板工具

https://okso.app https://drawio.com https://tldraw.com https://excalidraw.com

18 Transformer 的动态流程

博客配套视频链接: https://space.bilibili.com/383551518?spm_id_from333.1007.0.0 b 站直接看 配套 github 链接&#xff1a;https://github.com/nickchen121/Pre-training-language-model 配套博客链接&#xff1a;https://www.cnblogs.com/nickchen121/p/15105048.html 机…

npm install 报node-sass command failed

一、前言 最近在前端项目Vue项目install时会出现node-sass command failed的错误&#xff0c;原因是NodeJS和node-sass的版本不对应导致的&#xff0c;本文将给出解决方案。 二、解决方案 以下是NodeJS和node-sass版本的对照关系&#xff1a;

【Linux Screen命令】Linux用户注销后可长时间运行的命令行

1. 使用情境 你有没有这样的经历&#xff1a;你有一台远程计算机&#xff0c;并在上面执行长时间运行的任务&#xff0c;突然连接断开&#xff0c;SSH 会话终止&#xff0c;而导致你的工作进度丢失。 幸运的是&#xff0c;有一个名为 Screen 的实用程序可以让我们持续会话。甚…

C++前缀和算法的应用:摘水果 原理源码测试用例

本文涉及的基础知识点 C算法&#xff1a;前缀和、前缀乘积、前缀异或的原理、源码及测试用例 包括课程视频 题目 在一个无限的 x 坐标轴上&#xff0c;有许多水果分布在其中某些位置。给你一个二维整数数组 fruits &#xff0c;其中 fruits[i] [positioni, amounti] 表示共…

代码随想录 | Day63 总结篇

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 代码随想录刷题总结 代码随想录刷题总结 这应该是我第一次完整的刷完一本书&#xff0c;以前最多刷到树就会有畏惧和退缩心理&#xff0c;这次报名了卡哥的训练营&…

1221. 四平方和--(暴力,二分)

题目&#xff1a; 1221. 四平方和 - AcWing题库 思路1&#xff1a;暴力 暴力枚举 1.枚举顺序为从a到c&#xff0c;依次增大。 2.tn-a*a-b*b-c*c&#xff0c;求得dsqrt(t) 3.判断求出的d是否成立。d要求&#xff1a;d*dt&&d>c #include<iostream> #include&…

pytorch实战---IMDB情感分析

&#x1f497;&#x1f497;&#x1f497;欢迎来到我的博客&#xff0c;你将找到有关如何使用技术解决问题的文章&#xff0c;也会找到某个技术的学习路线。无论你是何种职业&#xff0c;我都希望我的博客对你有所帮助。最后不要忘记订阅我的博客以获取最新文章&#xff0c;也欢…

原始航片匀色调色方法

使用PhotoRC 2.0软件&#xff0c;对原始航片进行批量匀色&#xff0c;可以自动处理和人机交互&#xff0c;保留exif信息。 软件下载链接&#xff1a; https://pan.baidu.com/s/1Jj4cMpq8xzYvSa1hhozH-g?pwdndfm 提取码&#xff1a;ndfm

知识点滴 - Email地址不区分大小写

电子邮件地址本身对字符大小写不敏感。这意味着实际的电子邮件地址&#xff0c;如 "exampleemail.com"&#xff0c;并不区分字母的大小写。无论你输入的是大写字母还是小写字母&#xff0c;它仍然会到达同一个电子邮件账户。例如&#xff0c;如果您的电子邮件地址是 …

Linux 用户必备的 Git 图形化工具

Git 是一个免费的开源分布式版本控制系统&#xff0c;用于软件开发和其他几个版本控制任务。它旨在根据速度、效率和数据完整性来处理从小到大的项目。 Linux 用户主要可以通过命令行管理 Git&#xff0c;但是&#xff0c;有几个图形用户界面 (GUI) Git 客户端可以促进在 Linux…

DevOps持续集成-Jenkins(3)

文章目录 DevOpsDevOps概述Jenkins实战3&#xff1a;实战1和实战2的加强版&#xff08;新增SonarQube和Harbor&#xff09;⭐环境准备⭐项目架构图对比Jenkins实战1和实战2&#xff0c;新增内容有哪些&#xff1f;SonarQube教程采用Docker安装SonarQube &#xff08;在Jenkins所…

linux-防火墙

目录 一、防火墙概念 1.软件防火墙 2.iptables默认规则 3.iptables的五链 4.iptables动作 5.四表五链 6.iptables实例 一、防火墙概念 linux下防火墙一般分为软件防火墙、硬件防火墙 硬件防火墙&#xff1a;在硬件的级别实现防火墙过滤功能&#xff0c;性能高&#xf…

实践小记—静态成员的使用注意(或许由此产生的不知名Bug)

序言 在实际生产过程中&#xff0c;为了便于调用&#xff0c;static修饰的成员会比较容易出现。 如果后期该变量并不会被修改&#xff0c;可以考虑使用。但如果后期需要被修改&#xff0c;使用该变量修饰符则需要慎重考虑。 尤其是在对硬件控制的实际生产中&#xff0c;更需…

依据《中华人民共和国教育法》,以作弊、剽窃、抄袭等欺诈行为或者其他不正当手段获得学位证书、学历证书或者其他学业证书的,由( )撤销相关证书。

需要查看详细试题题库及其参考答案的&#xff0c;请到&#xff08;题海舟&#xff09;里进行搜索查看。可搜试题题干或者搜索关键词&#xff0c;搜题的时候&#xff0c;先进行题目识别&#xff0c;能大大提高学习效率&#xff0c;感谢使用&#xff01; 截取几个关键字查&#…

centos服务器搭建安装Gitlab教程使用教程

1、更新服务器&#xff1a; sudo yum update -y && sudo yum upgrade -y 2、下载Gitlab的RPM包 https://packages.gitlab.com/gitlab/gitlab-cece表示开源el表示centos 选64位el8对应CentOS8 本教程以centos8为例&#xff0c;在服务器中&#xff0c;下载centos8的…

基于Android 10系统的瑞芯微RK3399K烧写镜像实录

基于Android 10系统的瑞芯微RK3399K烧写镜像实录 1. 前言2. 官网及相关资料3. 烧写固件所需软件4. 直接烧写单一固件步骤5. 固件文件6. Windows下烧写准备6.1 安装 RK USB 驱动6.2 连接设备 7. 烧写固件7.1 烧写统一固件 update.img7.2 烧写分区映像 8. Linux下烧写8.1 upgrade…

STM32 HAL库串口使用printf

STM32 HAL库串口使用printf 背景配置说明在usart.h中添加在usart.c中添加在工程中选中微库&#xff1a; 测试 背景 在我们使用CubeMX生成好STM32 HAL库工程之后&#xff0c;我们想使用printf函数来打印一些信息&#xff0c;配置如下&#xff1a; 配置说明 在usart.h中添加 …

水电站与数据可视化:洞察未来能源趋势的窗口

在信息时代的浪潮中&#xff0c;数据可视化正成为推动能源领域发展的重要工具。今天&#xff0c;我们将带您一起探索水电站与数据可视化的结合&#xff0c;如何成为洞察未来能源趋势的窗口。水电站作为传统能源领域的重要组成部分&#xff0c;它的运行与管理涉及大量的数据。然…