正则表达式


正则表达式使用单个字符串来描述、匹配一系列匹配某个句法规则的字符串。

修饰符

在这里插入图片描述

元字符

所有元字符列表
在这里插入图片描述

1. 常用字符

代码说明
.匹配除换行符以外的任意字符
\w匹配字母或数字或下划线或汉字
\s匹配任意的空白符
\d匹配数字
\b匹配单词的开始或结束
^匹配字符串的开始
$匹配字符串的结束
1. 匹配有abc开头的字符串:\babc或者^abc
	
2. 匹配8位数字的QQ号码:^\d\d\d\d\d\d\d\d$
	
3. 匹配1开头11位数字的手机号码:^1\d\d\d\d\d\d\d\d\d\d$

2. 重复限定符

代码说明
*重复零次或更多次
+重复一次或更多次
?重复零次或一次
{n}重复n次
{n,}重复n次或更多次
{n,m}重复n到m次
1. 匹配8位数字的QQ号码: ^\d{8}$

2. 匹配1开头11位数字的手机号码: ^1\d{10}$

3. 匹配银行卡号是14~18位的数字:^\d{14,18}$

4. 匹配以a开头的,0个或多个b结尾的字符串^ab*$

3. 分组字符

代码说明
(()作为一个整体来进行分组
)()作为一个整体来进行分组
从上面的例子(4)中看到,*限定符是作用在与他左边最近的一个字符,但如果我想要ab同时被*限定那怎么办呢?

正则表达式中用小括号()来做分组,也就是括号中的内容作为一个整体。

因此当我们要匹配多个ab时,我们可以这样如:匹配字符串中包含0到多个ab开头:1   ^(ab)*

4. 转义字符

代码说明
| 将下一个字符标记为一个特殊字符、或一个原义字符、或一个 向后引用、或一个八进制转义符
如果你想查找元字符本身的话,比如你查找.,*,就出现了问题:

你没办法指定它们,因为它们会被解释成别的意思。

这时你就得使用\来取消这些字符的特殊意义。因此,你应该使用\.和\*。当然,要查找\本身,你也得用\\

5. 条件或

代码说明
|或,也叫做分支条件,当满足正则里的分支条件的任何一种条件时,都会当成是匹配成功
回到我们刚才的手机号匹配,我们都知道:国内号码都来自三大网,它们都有属于自己的号段,比如联通有
130/131/132/155/156/185/186/145/176等号段,假如让我们匹配一个联通的号码,那按照我们目前所学到的正则,
应该无从下手的,因为这里包含了一些并列的条件,也就是“或”,那么在正则中是如何表示“或”的呢?

正则用符号 | 来表示或,也叫做分支条件,当满足正则里的分支条件的任何一种条件时,都会当成是匹配成功。那么我
们就可以用或条件来处理这个问题1   ^(130|131|132|155|156|185|186|145|176)\d{8}$

6. 区间

代码说明
[]区间条件
正则提供一个元字符中括号 [] 来表示区间条件。限定0到9 可以写成[0-9]限定A-Z 写成[A-Z]限定某些数字
 [165]那上面的正则我们还改成这样:^((13[0-2])|(15[56])|(18[5-6])|145|176)\d{8}$

反义字符

代码说明
\W区间条件
\S匹配任意不是空白符的字符
\D匹配任意非数字的字符
\B匹配不是单词开头或结束的位置

另外

[^x]	匹配除了x以外的任意字符
[^aeiou]	匹配除了aeiou这几个字母以外的任意字符

对正则表达式的支持

在这里插入图片描述

进阶部分

1.零宽断言

无论是零宽还是断言,听起来都古古怪怪的,那先解释一下这两个词。

  1. 断言:
    俗话的断言就是“我断定什么什么”,而正则中的断言,就是说正则可以指明在指定的内容的前面或后面会出现满足指定规则的内容,意思正则也可以像人类那样断定什么什么,比如"ss1aa2bb3",正则可以用断言找出aa2前面有bb3,也可以找出aa2后面有ss1。
  2. 零宽:
    就是没有宽度,在正则中,断言只是匹配位置,不占字符,也就是说,匹配结果里是不会返回断言本身。
代码说明
(?=pattern)匹配pattern表达式的前面内容,不返回本身
(?<=pattern)匹配pattern表达式的后面内容,不返回本身
(?!pattern)匹配非pattern表达式的前面内容,不返回本身
(?<!pattern)匹配非pattern表达式的后面内容,不返回本身
下面先来讲几种类型的断言

1.1 正向先行断言(正前瞻)

语法:(?=pattern)
作用:匹配pattern表达式的前面内容,不返回本身。

回归刚才那个栗子,要取到阅读量,在正则表达式中就意味着要能匹配到‘’前面的数字内容按照上所说的正向先行断言可以匹配表达式前面的内容,那意思就是:(?=) 就可以匹配到前面的内容了。匹配什么内容呢?如果要所有内容那就是:

1   String reg=".+(?=</span>)";
 2
 3   String test = "<span class=\"read-count\">阅读数:641</span>";
 4   Pattern pattern = Pattern.compile(reg);
 5   Matcher mc=    pattern.matcher(test);
 6   while(mc.find()){
 7    System.out.println("匹配结果:")
 8    System.out.println(mc.group());
 9   }
10
11   //匹配结果:
12   //<span class="read-count">阅读数:641

可是老哥我们要的只是前面的数字呀,那也简单咯,匹配数字 \d,那可以改成:

1   String reg="\\d+(?=</span>)";
2   String test = "<span class=\"read-count\">阅读数:641</span>";
3   Pattern pattern = Pattern.compile(reg);
4   Matcher mc=    pattern.matcher(test);
5   while(mc.find()){
6     System.out.println(mc.group());
7   }
8   //匹配结果:
9   //641

1.2 正向后行断言(正后顾)

语法:(?<=pattern)
作用:匹配pattern表达式的后面的内容,不返回本身。

1   //(?<=<span class="read-count">阅读数:)\d+
 2   String reg="(?<=<span class=\"read-count\">阅读数:)\\d+";
 3
 4   String test = "<span class=\"read-count\">阅读数:641</span>";
 5   Pattern pattern = Pattern.compile(reg);
 6   Matcher mc=    pattern.matcher(test);
 7        while(mc.find()){
 8          System.out.println(mc.group());
 9        }
10   //匹配结果:
11   //641

1.3 负向先行断言(负前瞻)

语法:(?!pattern)
作用:匹配非pattern表达式的前面内容,不返回本身。

有正向也有负向,负向在这里其实就是非的意思。举个栗子:比如有一句 “我爱祖国,我是祖国的花朵”现在要找到不是’的花朵’前面的祖国用正则就可以这样写:1 祖国(?!的花朵)

1.4 负向后行断言(负后顾)

语法:(?<!pattern)
作用:匹配非pattern表达式的后面内容,不返回本身。

2. 捕获和非捕获

单纯说到捕获,他的意思是匹配表达式,但捕获通常和分组联系在一起,也就是“捕获组”。

捕获组:匹配子表达式的内容,把匹配结果保存到内存中中数字编号或显示命名的组里,以深度优先进行编号,之后可以通过序号或名称来使用这些匹配结果。
根据命名方式的不同,又可以分为两种组:

2.1 数字编号捕获组

语法:(exp)
解释:从表达式左侧开始,每出现一个左括号和它对应的右括号之间的内容为一个分组,在分组中,第0组为整个表达式,第一组开始为分组。
比如固定电话的:020-85653333
正则表达式为:(0\d{2})-(\d{8})
按照左括号的顺序,这个表达式有如下分组:
在这里插入图片描述

1   String test = "020-85653333";
 2        String reg="(0\\d{2})-(\\d{8})";
 3        Pattern pattern = Pattern.compile(reg);
 4        Matcher mc= pattern.matcher(test);
 5        if(mc.find()){
 6          System.out.println("分组的个数有:"+mc.groupCount());
 7            for(int i=0;i<=mc.groupCount();i++){
 8                System.out.println("第"+i+"个分组为:"+mc.group(i));
 9            }
10        }


输出结果:

1   分组的个数有:2
2   第0个分组为:020-85653333
3   第1个分组为:020
4   第2个分组为:85653333

可见,分组个数是2,但是因为第0个为整个表达式本身,因此也一起输出了。

2.2 命名编号捕获组

语法:(?exp)
解释:分组的命名由表达式中的name指定
比如区号也可以这样写:(?\0\d{2})-(?\d{8})
按照左括号的顺序,这个表达式有如下分组:
在这里插入图片描述

2.3 非捕获组

语法:(?:exp)
解释:和捕获组刚好相反,它用来标识那些不需要捕获的分组,说的通俗一点,就是你可以根据需要去保存你的分组。

比如上面的正则表达式,程序不需要用到第一个分组,那就可以这样写: (?:\0\d{2})-(\d{8})
在这里插入图片描述

1   String test = "020-85653333";
 2        String reg="(?:0\\d{2})-(\\d{8})";
 3        Pattern pattern = Pattern.compile(reg);
 4        Matcher mc= pattern.matcher(test);
 5        if(mc.find()){
 6                System.out.println("分组的个数有:"+mc.groupCount());
 7                for(int i=0;i<=mc.groupCount();i++){
 8                    System.out.println("第"+i+"个分组为:"+mc.group(i));
 9                }
10        }


输出结果:1   分组的个数有:1
2   第0个分组为:020-85653333
3   第1个分组为:85653333

3. 反向引用

我们知道:捕获会返回一个捕获组,这个分组是保存在内存中,不仅可以在正则表达式外部通过程序进行引用,也可以在正则表达式内部进行引用,这种引用方式就是反向引用。
根据捕获组的命名规则,反向引用可分为:

  1. 数字编号组反向引用:\k或\number
  2. 命名编号组反向引用:\k或者’name’

捕获组通常是和反向引用一起使用的上面说到捕获组是匹配子表达式的内容按序号或者命名保存起来以便使用。
注意两个字眼:“内容” 和 “使用”

  1. 内容:是匹配结果,而不是子表达式本身,强调这个有什么用。
  2. 使用:它的作用主要是用来查找一些重复的内容或者做替换指定字符。

举例说明:
比如要查找一串字母"aabbbbgbddesddfiid"里成对的字母
如果按照我们之前学到的正则,什么区间啊限定啊断言啊可能是办不到的
现在我们先用程序思维理一下思路:

  1. 匹配到一个字母
  2. 匹配第下一个字母,检查是否和上一个字母是否一样
  3. 如果一样,则匹配成功,否则失败

首先匹配一个字母:\w我们需要做成分组才能捕获,因此写成这样:(\w)

那这个表达式就有一个捕获组:(\w)

然后我们要用这个捕获组作为条件,那就可以:(\w)\1这样就大功告成了

\1是什么意思呢?
捕获组有两种命名方式,一种是是根据捕获分组顺序命名,一种是自定义命名来作为捕获组的命名在默认情况下都是以数字来命名,而且数字命名的顺序是从1开始的因此要引用第一个捕获组,根据反向引用的数字命名规则 就需要 \k<1>或者\1当然,通常都是是后者。

我们来测试一下:

1   String test = "aabbbbgbddesddfiid";
2        Pattern pattern = Pattern.compile("(\\w)\\1");
3        Matcher mc= pattern.matcher(test);
4        while(mc.find()){
5            System.out.println(mc.group());
6
7        }


输出结果:
1   aa
2   bb
3   bb
4   dd
5   dd
6   ii

嗯,这就是我们想要的了。
在举个替换的例子,假如想要把字符串中abc换成a

1   String test = "abcbbabcbcgbddesddfiid";
2   String reg="(a)(b)c";
3   System.out.println(test.replaceAll(reg, "$1"));

输出结果:
1   abbabcgbddesddfiid

4. 贪婪和非贪婪

4.1贪婪

我们都知道,贪婪就是不满足,尽可能多的要。在正则中,贪婪也是差不多的意思。

贪婪匹配:

  • 当正则表达式中包含能接受重复的限定符时,通常的行为是(在使整个表达式能得到匹配的前提下)匹配尽可能多的字符,这匹配方式叫做贪婪匹配。

特性:

  • 一次性读入整个字符串进行匹配,每当不匹配就舍弃最右边一个字符,继续匹配,依次匹配和舍弃(这种匹配-舍弃的方式也叫做回溯),直到匹配成功或者把整个字符串舍弃完为止,因此它是一种最大化的数据返回,能多不会少。

前面我们讲过重复限定符,其实这些限定符就是贪婪量词,比如表达式:1 \d{3,6}

用来匹配3到6位数字,在这种情况下,它是一种贪婪模式的匹配,也就是假如字符串里有6个个数字可以匹配,那它就是全部匹配到。

1   String reg="\\d{3,6}";        
2   String test="61762828 176 2991 871";
3   System.out.println("文本:"+test);
4   System.out.println("贪婪模式:"+reg);
5   Pattern p1 =Pattern.compile(reg);
6   Matcher m1 = p1.matcher(test);
7    while(m1.find()){
8      System.out.println("匹配结果:"+m1.group(0));
9   }

输出结果:

1   文本:61762828 176 2991 44 871
2   贪婪模式:\d{3,6}
3   匹配结果:617628
4   匹配结果:176
5   匹配结果:2991
6   匹配结果:871

由结果可见:本来字符串中的“61762828”这一段,其实只需要出现3个(617)就已经匹配成功了的,但是他并不满足,而是匹配到了最大能匹配的字符,也就是6个

多个贪婪在一起时,如果字符串能满足他们各自最大程度的匹配时,就互不干扰,但如果不能满足时,会根据深度优先原则,也就是从左到右的每一个贪婪量词,优先最大数量的满足,剩余再分配下一个量词匹配。

1   String reg="(\\d{1,2})(\\d{3,4})";        
2   String test="61762828 176 2991 87321";
3   System.out.println("文本:"+test);
4   System.out.println("贪婪模式:"+reg);
5   Pattern p1 =Pattern.compile(reg);
6   Matcher m1 = p1.matcher(test);
7    while(m1.find()){
8      System.out.println("匹配结果:"+m1.group(0));
9     }

输出结果:

1   文本:61762828 176 2991 87321
2   贪婪模式:(\d{1,2})(\d{3,4})
3   匹配结果:617628
4   匹配结果:2991
5   匹配结果:8732
“617628” 是前面的\d{1,2}匹配出了61,后面的匹配出了7628

"2991" 是前面的\d{1,2}匹配出了29 ,后面的匹配出了91

"87321"是前面的\d{1,2}匹配出了87,后面的匹配出了321

4.2 懒惰(非贪婪)

懒惰匹配:

  • 当正则表达式中包含能接受重复的限定符时,通常的行为是(在使整个表达式能得到匹配的前提下)匹配尽可能少的字符,这匹配方式叫做懒惰匹配。

特性:

  • 从左到右,从字符串的最左边开始匹配,每次试图不读入字符匹配,匹配成功,则完成匹配,否则读入一个字符再匹配,依此循环(读入字符、匹配)直到匹配成功或者把字符串的字符匹配完为止。懒惰量词是在贪婪量词后面加个“?”
    在这里插入图片描述
1   String reg="(\\d{1,2}?)(\\d{3,4})";        
2        String test="61762828 176 2991 87321";
3        System.out.println("文本:"+test);
4        System.out.println("贪婪模式:"+reg);
5        Pattern p1 =Pattern.compile(reg);
6        Matcher m1 = p1.matcher(test);
7        while(m1.find()){
8            System.out.println("匹配结果:"+m1.group(0));
9        }

输出结果:

1   文本:61762828 176 2991 87321
2   贪婪模式:(\d{1,2}?)(\d{3,4})
3   匹配结果:61762
4   匹配结果:2991
5   匹配结果:87321

解答:
“61762” 是左边的懒惰匹配出6,右边的贪婪匹配出1762
"2991"  是左边的懒惰匹配出2,右边的贪婪匹配出991
"87321" 左边的懒惰匹配出8,右边的贪婪匹配出7321

常用正则表达式

一、校验数字的表达式

- 数字:^[0-9]*$
- n位的数字:^\d{n}$
- 至少n位的数字:^\d{n,}$
- m-n位的数字:^\d{m,n}$
- 零和非零开头的数字:^(0|[1-9][0-9]*)$
- 非零开头的最多带两位小数的数字:^([1-9][0-9]*)+(\.[0-9]{1,2})?$
- 带1-2位小数的正数或负数:^(\-)?\d+(\.\d{1,2})$
- 正数、负数、和小数:^(\-|\+)?\d+(\.\d+)?$
- 有两位小数的正实数:^[0-9]+(\.[0-9]{2})?$
- 有1~3位小数的正实数:^[0-9]+(\.[0-9]{1,3})?$
- 非零的正整数:^[1-9]\d*$ 或 ^([1-9][0-9]*){1,3}$ 或 ^\+?[1-9][0-9]*$
- 非零的负整数:^\-[1-9][]0-9"*$ 或 ^-[1-9]\d*$
- 非负整数:^\d+$ 或 ^[1-9]\d*|0$
- 非正整数:^-[1-9]\d*|0$ 或 ^((-\d+)|(0+))$
- 非负浮点数:^\d+(\.\d+)?$ 或 ^[1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0$
- 非正浮点数:^((-\d+(\.\d+)?)|(0+(\.0+)?))$ 或 ^(-([1-9]\d*\.\d*|0\.\d*[1-9]\d*))|0?\.0+|0$
- 正浮点数:^[1-9]\d*\.\d*|0\.\d*[1-9]\d*$ 或 ^(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*))$
- 负浮点数:^-([1-9]\d*\.\d*|0\.\d*[1-9]\d*)$ 或 ^(-(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*)))$
- 浮点数:^(-?\d+)(\.\d+)?$ 或 ^-?([1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0)$

二、校验字符的表达式


- 汉字:^[\u4e00-\u9fa5]{0,}$
- 英文和数字:^[A-Za-z0-9]+$ 或 ^[A-Za-z0-9]{4,40}$
- 长度为3-20的所有字符:^.{3,20}$
- 由26个英文字母组成的字符串:^[A-Za-z]+$
- 由26个大写英文字母组成的字符串:^[A-Z]+$
- 由26个小写英文字母组成的字符串:^[a-z]+$
- 由数字和26个英文字母组成的字符串:^[A-Za-z0-9]+$
- 由数字、26个英文字母或者下划线组成的字符串:^\w+$ 或 ^\w{3,20}$
- 中文、英文、数字包括下划线:^[\u4E00-\u9FA5A-Za-z0-9_]+$
- 中文、英文、数字但不包括下划线等符号:^[\u4E00-\u9FA5A-Za-z0-9]+$ 或 ^[\u4E00-\u9FA5A-Za-z0-9]{2,20}$
- 可以输入含有^%&',;=?$\"等字符:[^%&',;=?$\x22]+
- 禁止输入含有~的字符:[^~\x22]+

三、特殊需求表达式

- Email地址:^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$
- 域名:[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+\.?
- InternetURL:[a-zA-z]+://[^\s]* 或 ^http://([\w-]+\.)+[\w-]+(/[\w-./?%&=]*)?$
- 手机号码:^(13[0-9]|14[5|7]|15[0|1|2|3|4|5|6|7|8|9]|18[0|1|2|3|5|6|7|8|9])\d{8}$
- 电话号码("XXX-XXXXXXX"、"XXXX-XXXXXXXX"、"XXX-XXXXXXX"、"XXX-XXXXXXXX"、"XXXXXXX"和"XXXXXXXX):^(\(\d{3,4}-)|\d{3.4}-)?\d{7,8}$
- 国内电话号码(0511-4405222、021-87888822):\d{3}-\d{8}|\d{4}-\d{7}
- 电话号码正则表达式(支持手机号码,3-4位区号,7-8位直播号码,1-4位分机号): ((\d{11})|^((\d{7,8})|(\d{4}|\d{3})-(\d{7,8})|(\d{4}|\d{3})-(\d{7,8})-(\d{4}|\d{3}|\d{2}|\d{1})|(\d{7,8})-(\d{4}|\d{3}|\d{2}|\d{1}))$)
- 身份证号(15位、18位数字),最后一位是校验位,可能为数字或字符X:(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)
- 帐号是否合法(字母开头,允许5-16字节,允许字母数字下划线):^[a-zA-Z][a-zA-Z0-9_]{4,15}$
- 密码(以字母开头,长度在6~18之间,只能包含字母、数字和下划线):^[a-zA-Z]\w{5,17}$
- 强密码(必须包含大小写字母和数字的组合,不能使用特殊字符,长度在 8-10 之间):^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])[a-zA-Z0-9]{8,10}$
- 强密码(必须包含大小写字母和数字的组合,可以使用特殊字符,长度在8-10之间):^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,10}$
- 日期格式:^\d{4}-\d{1,2}-\d{1,2}
- 一年的12个月(01~09和1~12):^(0?[1-9]|1[0-2])$
- 一个月的31天(01~09和1~31):^((0?[1-9])|((1|2)[0-9])|30|31)$
- 钱的输入格式:
	- 有四种钱的表示形式我们可以接受:"10000.00" 和 "10,000.00", 和没有 "分" 的 "10000" 和 "10,000":^[1-9][0-9]*$
	- 这表示任意一个不以0开头的数字,但是,这也意味着一个字符"0"不通过,所以我们采用下面的形式:^(0|[1-9][0-9]*)$
	- 一个0或者一个不以0开头的数字.我们还可以允许开头有一个负号:^(0|-?[1-9][0-9]*)$
	- 这表示一个0或者一个可能为负的开头不为0的数字.让用户以0开头好了.把负号的也去掉,因为钱总不能是负的吧。下面我们要加的是说明可能的小数部分:^[0-9]+(.[0-9]+)?$
	- 必须说明的是,小数点后面至少应该有1位数,所以"10."是不通过的,但是 "10" 和 "10.2" 是通过的:^[0-9]+(.[0-9]{2})?$
	- 这样我们规定小数点后面必须有两位,如果你认为太苛刻了,可以这样:^[0-9]+(.[0-9]{1,2})?$
	- 这样就允许用户只写一位小数.下面我们该考虑数字中的逗号了,我们可以这样:^[0-9]{1,3}(,[0-9]{3})*(.[0-9]{1,2})?$
	- 1到3个数字,后面跟着任意个 逗号+3个数字,逗号成为可选,而不是必须:^([0-9]+|[0-9]{1,3}(,[0-9]{3})*)(.[0-9]{1,2})?$
- xml文件:^([a-zA-Z]+-?)+[a-zA-Z0-9]+\\.[x|X][m|M][l|L]$
- 中文字符的正则表达式:[\u4e00-\u9fa5]
- 双字节字符:[^\x00-\xff] (包括汉字在内,可以用来计算字符串的长度(一个双字节字符长度计2,ASCII字符计1))
- 空白行的正则表达式:\n\s*\r (可以用来删除空白行)
- HTML标记的正则表达式:<(\S*?)[^>]*>.*?|<.*? /> ( 首尾空白字符的正则表达式:^\s*|\s*$或(^\s*)|(\s*$) (可以用来删除行首行尾的空白字符(包括空格、制表符、换页符等等),非常有用的表达式)
- 腾讯QQ号:[1-9][0-9]{4,} (腾讯QQ号从10000开始)
- 中国邮政编码:[1-9]\d{5}(?!\d) (中国邮政编码为6位数字)
- IPv4地址:((2(5[0-5]|[0-4]\d))|[0-1]?\d{1,2})(\.((2(5[0-5]|[0-4]\d))|[0-1]?\d{1,2})){3}

参考文章:
你是如何学会正则表达式的?

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值