python基础-6正则表达式
⼀ python正则简介
就其本质⽽⾔,正则表达式(或 RE)是⼀种⼩型的、⾼度专业化的编程语⾔,(在Python中)它内嵌在Python中,并通过 re 模块实现。
正则表达式模式被编译成⼀系列的字节码,然后由⽤ C 编写的匹配引擎执⾏。
正则表达式并不是Python的⼀部分。正则表达式是⽤于处理字符串的强⼤⼯具,拥有⾃⼰独特的语法以及⼀个独⽴的处理引擎,效率上可能不如str⾃带的⽅法,但功能⼗分
强⼤。得益于这⼀点,在提供了正则表达式的语⾔⾥,正则表达式的语法都是⼀样的,区别只在于不同的编程语⾔实现⽀持的语法数量不同;但不⽤担⼼,不被⽀持的语法通常
是不常⽤的部分。如果已经在其他语⾔⾥使⽤过正则表达式,只需要简单看⼀看就可以上⼿了。
下图展⽰了使⽤正则表达式进⾏匹配的流程:
正则表达式的⼤致匹配过程是:依次拿出表达式和⽂本中的字符⽐较,如果每⼀个字符都能匹配,则匹配成功;⼀旦有匹配不成功的字符则匹配失败。如果表达式中有量词或边
界,这个过程会稍微有⼀些不同,但也是很好理解的,看下图中的⽰例以及⾃⼰多使⽤⼏次就能明⽩。
⼆ python正则的字符
1 普通字符
⼤多数字符和字母都会和⾃⾝匹配
1 >>> re.findall('alex','yuanaleSxalexwupeiqi')
2 ['alex']
2 元字符
元字符:. ^ $ * + ? { } [ ] | ( ) \
1正则表达式:
2字符匹配:元字符 []
3 . :任意单个字符
4 []:指定范围内的的任意单个字符
5 [0-9]
6 [a-z]
7 [A-Z]
8 [^]:指定范围内的任意单个字符
9字符次数匹配:⽤来指定匹配其前⾯字符的次数
10 * :任意次数 0次 1次或多次
11例⼦:x*y x出现了y次 xxy xy y。
12 .*:匹配任意长度的字符
13 ?: 0次或1次
14 x\?y xy y xxy
15贪婪模式:尽可能长的去匹配字符
16
17 + 1次或多次
18 {m}:,匹配m次
19 {m,n}:m次到n次
20 {m,}:⾄少m次
21 {0,n}:⾄多n次
22位置锚定:⽤于指定字符出现的位置
23 ^ :⽤于锚定⾏⾸
24 ^Char 以Char开头
25 $ :锚定⾏尾
26 char$ 以char结尾
27 ^$:空⽩⾏
28
29 \b : 锚定词⾸ \bchar
30 : 锚定词尾, char\b
31例如: \bhello\b 匹配hello单词
32分组:
33元字符( )
34 ab*xy 0个或者多个b
35 \(ab\)*xy 0个或者多个ab
36引⽤:
37
38 \1: 后向引⽤,引⽤前⾯的第⼀个左括号以及与之对应的左括号中的模式所匹配到的内容
39 \2
40 .....
41 (a.b)(c.d\)xy\1\2 : 必须再次出现前⾯括号分组的内容实体1次后⾯的引⽤内容不再是正则
42
43 a3bc2dxya3bc2d
44 元字符 \ :
45 ?1234567\d 匹配任何⼗进制数;它相当于类 [0-9]。\D 匹配任何⾮数字字符;它相当于类 [^0-9]。\s 匹配任何空⽩字符;它相当于类 [ \t\n\r\f\v]。\S 匹配任何⾮空⽩字符;它相当于类 [^ \t\n\r\f\v]。\w 匹配任何字母数字字符;它相当于类 [a-zA-Z0
2.1 python 元字符 []说明
我们⾸先考察的元字符是"[" 和 "]"。
它们常⽤来指定⼀个字符类别,所谓字符类别就是你想匹配的⼀个字符集。输出所有符合的字符,单个单个的字符
字符可以单个列出,也可以⽤“-”号分隔的两个给定字符来表⽰⼀个字符区间。
例如,[abc] 将匹配"a", "b", 或 "c"中的任意⼀个字符;也可以⽤区间[a-c]来表⽰同⼀字符集,和前者效果⼀致。如果你只想匹配⼩写字母,那么 RE 应写成 [a-z].
元字符在字符集并不起作⽤。元字符在中括号[]内就代表字符
1 re.findall("[abc]","yuanaleSxalexwupeiqi")
2 ['a', 'a', 'a']
3 re.findall("[a-c]","yuanaleSxalexwupeiqi")
4 ['a', 'a', 'a']
5 re.findall("[a-q]","yuanaleSxalexwupeiqi")
6 ['a', 'n', 'a', 'l', 'e', 'a', 'l', 'e', 'p', 'e', 'i', 'q', 'i']
7 re.findall("[(an)]","yuanaleSxalexwupeiqi")
8 ['a', 'n', 'a', 'a']
9 re.findall("[an]","yuanaleSxalexwupeiqi")
10 ['a', 'n', 'a', 'a']
1 >>> a = "123 ..*#$% ABC abc"
2
3 >>> re.findall("[..*]",a)
4 ['.', '.', '*']
[]:元字符[]表⽰字符类,在⼀个字符类[]中,只有字符^、-、]和\有特殊含义。
[^x]匹配除了x以外的任意字符
[^aeiou]匹配除了aeiou这⼏个字母以外的任意字符
例如,[akm$]将匹配字符"a", "k", "m", 或 "$" 中的任意⼀个;"$"通常⽤作元字符,但在字符类别⾥,其特性被除去,恢复成普通字符。
测试
1 >>> re.findall("[akm$]","a$kcc3")
2 <strong>['a', '$', 'k']
3 </strong>
2.2 python元字符()说明结合引⽤:
括号内的为⼀个整体,分组。
1 re.findall("a\d+","a234b")
2 ['a234']
3 re.findall("a(\d+)","a234b")
4 ['234']
5 re.findall("a\d{1,2}","a234b")
6 ['a23']
7 re.findall("a(\w+)","aaabbc4b")
8 ['aabbc4b']
9 re.findall("ab(\d+)","aaabbc4b")
10 []
11 re.findall("ab(\w+)","aaabbc4b")
12 ['bc4b']
13
14#括号前⾯是限定条件,只查括号⾥⾯的,findall取的是组⾥⾯的内容,优先捕获。加上?:去掉
re.findall(r"a(\d+?)","a234b")
'a234'
测试
1 >>> p = repile('(a(b)c)d')
2 >>> m = p.match('abcd')
3 >>> m.group(0)
4'abcd'
5 >>> m.group(1)
6'abc'
7 >>> m.group(2)
8'b'
1 <strong>⽐如vim正则该love 为Love</strong><br> he love her love l⼤写 he Love her love
2 <span >:1,20s@\(l\(..e\)\)\(.*\1\)@L\2\3@g</span>
3 \1: 后向引⽤,引⽤前⾯的第⼀个左括号以及与之对应的左括号中的模式所匹配到的内容 \1 = 前⾯括号内容,前⾯内容是什么\1就是什么上⾯即 \1 =l \2 =ove
标签引⽤分组
(?P<sign>\d+)(?P=sign) == (\d+)\1
P<sign>作为分组名 . 任意字符 \d 数字 ?P=sign 引⽤
1 >>> re.match(r'(\w+) (\w+)(?P<sign>.)\d(?P=sign)', 'hello world!3!').group()
2'hello world!3!'
2.3 python + * ? {} 说明
+ 匹配+号前内容1次⾄⽆限次
匹配?号前内容0次到1次
{m} 匹配前⾯的内容m次
{m,n} 匹配前⾯的内容m到n次
*?,+?,??,{m,n}? 前⾯的*,+,?等都是贪婪匹配,也就是尽可能匹配,后⾯加?号使其变成惰性匹配
贪婪模式和⾮贪婪模式区别:
从前⾯的描述可以看到'*','+'和'?'都是贪婪的,但这也许并不是我们说要的,所以,可以在后⾯加个问号,将策略改为⾮贪婪,只匹配尽量少的RE。⽰例,
1体会两者的区别: <strong>findall 只匹配输出分组内容如果是分组的话,如果不是分组的话都输出匹配到输出的内容</strong> 后⾯介绍
2 >>> re.findall(r"a(\d+?)","a234b") # ⾮贪婪模式如果\d+匹配的是两个数字的话,
3 ['2']
4 >>> re.findall(r"a(\d+)","a234b")
5 ['234']
正则表达式通常⽤于在⽂本中查匹配的字符串。Python⾥数量词默认是贪婪的(在少数语⾔⾥也可能是默认⾮贪婪),总是尝试匹配尽可能多的字符;⾮贪婪的则相反,总是尝试匹配尽可能少的字符。例如:正则表达式"ab*"如果⽤于查"abbbc",将到"abbb"。⽽如果使⽤⾮贪婪的数量词"ab*?",将到"a"
1 >>> re.search('<(.*)>', '<H1>title</H1>').group()
2'<H1>title</H1>'
3 re.search('<(.*?)>', '<H1>title</H1>').group()
4'<H1>'
#如果前后均有限定条件,则⾮贪婪模式失效
1注意⽐较这种情况:
2 >>> re.findall(r"a(\d+)b","a23b")
3 ['23']
4 >>> re.findall(r"a(\d+?)b","a23b") #如果前后均有限定条件,则⾮匹配模式失效,不按照⾮贪婪模式
5 ['23']
2.4 python元字符 \ 说明
\:
反斜杠后边跟元字符去除特殊功能,字符转义
如果你想查元字符本⾝的话,⽐如你查.,或者*,就出现了问题:你没办法指定它们,因为它们会被解释成别的意思。这时你就得使⽤\来取消这些字符的特殊意义。
因此,你应该使⽤\.和\*。当然,要查\本⾝,你也得⽤\\.
例如:deerchao\匹配deerchao,C:\\Windows匹配C:\Windows。
反斜杠后边跟普通字符实现特殊功能。
引⽤序号对应的字组所匹配的字符串
1 \d 匹配任何⼗进制数;它相当于类 [0-9]。
3 \s 匹配任何空⽩字符;它相当于类 [ \t\n\r\f\v]。
4 \S 匹配任何⾮空⽩字符;它相当于类 [^ \t\n\r\f\v]。
5 \w 匹配任何字母数字字符;它相当于类 [a-zA-Z0-9_]。
6 \W 匹配任何⾮字母数字字符;它相当于类 [^a-zA-Z0-9_]
7 \b: 匹配⼀个单词边界,也就是指单词和空格间的位置。
1 >>> a = "123 ..*#$% ABC abc"<br>>>> re.findall("\d",a)
2 ['1', '2', '3']
3 >>> re.findall("\s",a)
4 ['', '', '']
5 >>> re.findall("\w",a)
6 ['1', '2', '3', 'A', 'B', 'C', 'a', 'b', 'c']
7 >>> re.findall("\D",a)
8 ['', '.', '.', '*', '#', '$', '%', '', 'A', 'B', 'C', '', 'a', 'b', 'c']
9 >>> re.findall("\S",a)
10 ['1', '2', '3', '.', '.', '*', '#', '$', '%', 'A', 'B', 'C', 'a', 'b', 'c']
11 >>> re.findall("\W",a)
12 ['', '.', '.', '*', '#', '$', '%', '', '']
13 >>>
例如, 'er\b' 可以匹配"never" 中的 'er',但不能匹配 "verb" 中的 'er'。
\b只是匹配字符串开头结尾及空格回车等的位置, 不会匹配空格符本⾝
例如 "abc sdsadasabcasdsadasdabcasdsa",
\sabc\s不能匹配,\babc\b可以匹配到"abc"
带\ 转义符需要⽤r 忽略python的制表符查
1 >>> re.findall("\babc\b","abc sdsadasabcasdsadasdabcasdsa") #这⾥匹配不到是因为没加r的原因,后⾯说明
2 []
3 >>> re.findall(r"\babc\b","abc sdsadasabcasdsadasdabcasdsa")
4 ['abc']
1 \b 就是⽤在你匹配整个单词的时候。如果不是整个单词就不匹配。你想匹配 I 的话,你知道,很多单词⾥都有I的,但我只想匹配I,就是“我”,这个时候⽤ \bI\b
2
python正则表达式匹配小数3最后讲r作⽤
1 >>> re.findall(r"\bI","I love u")
2 ['I']
>>> re.findall(r"\bIl","Ilove u")
['Il']
2.5反义
有时需要查不属于某个能简单定义的字符类的字符。⽐如想查除了数字以外,其它任意字符都⾏的情况,这时需要⽤到反义:
表3.常⽤的反义代码
代码/语法说明
\W匹配任意不是字母,数字,下划线,汉字的字符
\S匹配任意不是空⽩符的字符
\D匹配任意⾮数字的字符
\B匹配不是单词开头或结束的位置
[^x]匹配除了x以外的任意字符
[^aeiou]匹配除了aeiou这⼏个字母以外的任意字符
例⼦:\S+匹配不包含空⽩符的字符串。
<a[^>]+>匹配⽤尖括号括起来的以a开头的字符串。
2.6分⽀条件
不幸的是,刚才那个表达式也能匹配010)12345678或(022-********这样的“不正确”的格式。要解决这个问题,我们需要⽤到分枝条件。正则表达式⾥的分枝条件指的是有⼏种规则,如果满⾜其中任意⼀种规则都应该当成匹配,具体⽅法是⽤|把不同的规则分隔开。听不明⽩?没关系,看例⼦:
0\d{2}-\d{8}|0\d{3}-\d{7}这个表达式能匹配两种以连字号分隔的电话号码:⼀种是三位区号,8位本地号(如010-********),⼀种是4位区号,7位本地号(0376-*******)。
\(?0\d{2}\)?[- ]?\d{8}|0\d{2}[- ]?\d{8}这个表达式匹配3位区号的电话号码,其中区号可以⽤⼩括号括起来,也可以不⽤,区号与本地号间可以⽤连字号或空格间隔,也可以没有间隔。你可以试试⽤分枝条件把这个表达式扩展成也⽀持4位区号的。
\d{5}-\d{4}|\d{5}这个表达式⽤于匹配美国的。美国邮编的规则是5位数字,或者⽤连字号间隔的9位数字。之所以要给出这个例⼦是因为它能说明⼀个问题:使⽤分枝条件时,要注意各个条件的顺序。如果你把它改成\d{5}|\d{5}-\d{4}的话,那么就只会匹配5位的邮编(以及9位邮编的前5位)。原因是匹配分枝条件时,将会从左到右地测试每个条件,如果满⾜了某个分枝的话,就不会去再管其它的条件了。
三正则re模块的各种⽅法
1、match(pattern, string, flags=0)
从起始位置开始根据模型去字符串中匹配指定内容,匹配单个。没有匹配,返回值为None
正则表达式 patter
要匹配的字符串 string
标志位,⽤于控制正则表达式的匹配⽅式 flags
代码
1import re
2
3 obj = re.match('\d+', '123uuasf')#是⼀个对象,需要⽤group()⽅法提交返回值
4if obj:
up()
开头没有数字,因此返回None
标志位
re.M 会匹配每⼀⾏,处理⽂件可以
1 re.I 使匹配对⼤⼩写不敏感
2 re.L 做本地化识别(locale-aware)匹配
3 re.M 多⾏匹配,影响 ^ 和 $
4 re.S 使 . 匹配包括换⾏在内的所有字符
5 re.U 根据Unicode字符集解析字符。这个标志影响 \w, \W, \b, \B.
6 re.X 该标志通过给予你更灵活的格式以便你将正则表达式写得更易于理解。
标志位测试
1 re.I 使匹配对⼤⼩写不敏感
2 re.L 做本地化识别(locale-aware)匹配
3 re.M 多⾏匹配,影响 ^ 和 $
4 re.S 使 . 匹配包括换⾏在内的所有字符
5 >>> re.findall(".","abc\nde")
6 >>> re.findall(".","abc\nde",re.S)
7 re.U 根据Unicode字符集解析字符。这个标志影响 \w, \W, \b, \B.
8 re.X 该标志通过给予你更灵活的格式以便你将正则表达式写得更易于理解。
9
10 re.S:.将会匹配换⾏符,默认.逗号不会匹配换⾏符
11 >>> re.findall(r"a(\d+)b.+a(\d+)b","a23b\na34b")
12 []
13 >>> re.findall(r"a(\d+)b.+a(\d+)b","a23b\na34b",re.S)
14 [('23','34')]
15 >>>
16 re.M:^$标志将会匹配每⼀⾏,默认^只会匹配符合正则的第⼀⾏;默认$只会匹配符合正则的末⾏
17 >>> re.findall(r"^a(\d+)b","a23b\na34b")
18 ['23']
19 >>> re.findall(r"^a(\d+)b","a23b\na34b",re.M)
20 ['23','34']
21但是,如果没有^标志,
22 >>> re.findall(r"a(\d+)b","a23b\na34b")
23 ['23','43']
24可见,是⽆需re.M
1 re.x # X(VERBOSE): 详细模式。这个模式下正则表达式可以是多⾏,忽略空⽩字符,并可以加⼊注释。以下两个正则表达式是等价的:
2 a = repile(r"""\d + # the integral part
3 \. # the decimal point
4 \d * # some fractional digits""", re.X)
5 b = repile(r"\d+\.\d*")
测试
1 match 只从开头匹配匹配到就输出=== 字符串
2 obj = re.match('\d+', '123uuasf')
up())
4if obj:
up())
6 obj = re.match('\d+', '123uuasf')
7输出C:\ E:/py_test/s8/s4.py123123
1 match 如果开头没匹配到或者规则根本就都不匹配所有符合的直接返回None,调⽤grou()⽅法就报错
2 obj = re.match('\d+', 'sdfuuasf')
up())
4if obj:
up())
6
7报错如下
8 C:\ E:/py_test/s8/s4.py
9 Traceback (most recent call last):
10 File "E:/py_test/s8/s4.py", line 8, in <module>
up())
12 AttributeError: 'NoneType' object has no attribute 'group'
标志位练习
1 ============================
2import re
3 a = 'a23b'
4print re.findall('a(\d+?)',a) #['2'],\d+,重复⼀次以上。加上?只取最⼩次数,1次。findall查括号中的字符组
5print re.findall('a(\d+)',a) #['23'],\d+重复⼀次以上。
6print re.findall(r'a(\d+)b',a) #['23']
7print re.findall(r'a(\d+?)b',a) # ['23'],前后均有限定条件,因此⾮匹配模式失效,不按照贪婪模式查
8 ============================
9 b='a23b\na34b'
10''' . 匹配⾮换⾏符的任意⼀个字符'''
11
12 re.findall(r'a(\d+)b.+a(\d+)b',b) #[],没有将换⾏符去掉。b中有个\n.
13
14 re.findall(r'a(\d+)b',b,re.M) # ['23', '34']
15
16 re.findall(r'^a(\d+)b',b,re.M) # ['23', '34']
17
18 re.findall(r'a(\d+)b',b) #['23','34'] 可以匹配多⾏
19
20 re.findall(r'^a(\d+)b',b) # ['23'] 默认^只会匹配符合正则的第⼀⾏
21
22 re.findall(r'a(\d+)b$',b) # ['34'] 默认$只会匹配符合正则的末⾏
23
24 re.findall(r'a(\d+)b',b,re.M) #['23', '34']
25
26 re.findall(r'a(\d+)b.?',b,re.M) # ['23', '34']
27
28 re.findall(r"a(\d+)b", "a23b\na34b") # ['23', '34']
29 ---------------------------------------------------------------
Match对象是⼀次匹配的结果,包含了很多关于此次匹配的信息,可以使⽤Match提供的可读属性或⽅法来获取这些信息。
属性:
1. string: 匹配时使⽤的⽂本。
2. re: 匹配时使⽤的Pattern对象。
3. pos: ⽂本中正则表达式开始搜索的索引。值与Pattern.match()和Pattern.seach()⽅法的同名参数相同。
4. endpos: ⽂本中正则表达式结束搜索的索引。值与Pattern.match()和Pattern.seach()⽅法的同名参数相同。
5. lastindex: 最后⼀个被捕获的分组在⽂本中的索引。如果没有被捕获的分组,将为None。
6. lastgroup: 最后⼀个被捕获的分组的别名。如果这个分组没有别名或者没有被捕获的分组,将为None。
⽅法:
1. group([group1, …]):
获得⼀个或多个分组截获的字符串;指定多个参数时将以元组形式返回。group1可以使⽤编号也可以使⽤别名;编号0代表整个匹配的⼦串;不填写参数时,返回group(0);没有截获字符串的组返回None;截获了多次的组返回最后⼀次截获的⼦串。
2. groups([default]):
以元组形式返回全部分组截获的字符串。相当于调⽤group(1,2,…last)。default表⽰没有截获字符串的组以这个值替代,默认为None。
3. groupdict([default]):
返回以有别名的组的别名为键、以该组截获的⼦串为值的字典,没有别名的组不包含在内。default含义同上。
4. start([group]):
返回指定的组截获的⼦串在string中的起始索引(⼦串第⼀个字符的索引)。group默认值为0。
5. end([group]):
返回指定的组截获的⼦串在string中的结束索引(⼦串最后⼀个字符的索引+1)。group默认值为0。
6. span([group]):
返回(start(group), end(group))。
7. expand(template):
将匹配到的分组代⼊template中然后返回。template中可以使⽤\id或\g<id>、\g<name>引⽤分组,但不能使⽤编号0。\id与\g<id>是等价的;但\10将被认为是第10个分组,如果你想表达\1之后是字符'0',只
能使⽤\g<1>0。
# _*_ coding:utf-8 _*_
__author__ = 'liujianzuo'
import re
m = re.match(r'(\w+) (\w+)(?P<sign>.*)', 'hello world!')
print(r"m.string:", m.string)
print(:", m.re)
print(r"m.pos:", m.pos)
print(dpos:", m.endpos)
print(r"m.lastindex:", m.lastindex)
print(r"m.lastgroup:", m.lastgroup)
print(up(1,2):", m.group(1, 2))
print(ups():", m.groups())
print(updict():", m.groupdict())
print(r"m.start(2):", m.start(2))
print(d(2):", m.end(2))
print(r"m.span(2):", m.span(2))
print(pand(r'\2 \1\3'):", m.expand(r'\2 \1\3'))
1 C:\ E:/py_test/s7/re_match.py
2 m.string: hello world!
: repile('(\\w+) (\\w+)(?P<sign>.*)')
4 m.pos: 0
dpos: 12
6 m.lastindex: 3
7 m.lastgroup: sign
up(1,2): ('hello', 'world')
ups(): ('hello', 'world', '!')
updict(): {'sign': '!'}
11 m.start(2): 6
d(2): 11
13 m.span(2): (6, 11)
pand(r'\2 \1\3'): world hello!
2 search(pattern, string, flags=0)
根据模型去字符串中匹配指定内容,匹配单个,只匹配⼀次,匹配第⼀个,可以结合split 将匹配到内容分割拼接然后再次循环查。因为findall尽管可以到所有,但是在处理分组()时候分组外的内容匹配不到。⽽findall是返回列表后⾯会有介绍
代码
1import re
2
3 obj = re.search('\d+', 'u123uu888asf')
4if obj:
up()
标志位同上解释
search练习,和match类似,返回值是⼀个对象或None,
1 search 如果匹配到⼀个就退出了。
2import re
3
4 obj = re.search('\d+', 'u123uu888asf')
5if obj:
up())
7 C:\ E:/py_test/s8/s4.py
8 123
9
10 search 如果匹配不到 group()会报错
11
12import re
13 obj = re.search('\d+', 'sdfuuasf')
14
up())
16if obj:
up())
18
19 C:\ E:/py_test/s8/s4.py
20 Traceback (most recent call last):
21 File "E:/py_test/s8/s4.py", line 18, in <module>
up())
23 AttributeError: 'NoneType' object has no attribute 'group'
3、group和groups
group(0) 显⽰全部
group(1) 显⽰第⼀个分组()
group(2) 显⽰第⼆个分组()
如果没有分组或超出分组个数就会报错
1 a = "123abc456"
2print re.search("([0-9]*)([a-z]*)([0-9]*)", a).group()
3
4print re.search("([0-9]*)([a-z]*)([0-9]*)", a).group(0) #
5print re.search("([0-9]*)([a-z]*)([0-9]*)", a).group(1)
6print re.search("([0-9]*)([a-z]*)([0-9]*)", a).group(2)
7
8print re.search("([0-9]*)([a-z]*)([0-9]*)", a).groups()
4 findall
以列表形式返回所有匹配的字符串
re.findall可以获取字符串中所有匹配的字符串。
搜索string,以列表形式返回全部能匹配的⼦串。
1import re
2
3 p = repile(r'\d+')
4print p.findall('one1two2three3four4')
5
6### output ###
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论