正则环视 php,正则表达式基本知识(php)

这里的知识点基本上是《正则指引》的读书笔记,只是每个知识点的示例代码用php来实现。

1. 字符组

字符组(Character Class)就是一组字符,在正则表达式中,它表示“在同一个位置可能出现的各种字符”。

写法:[ab]、[314]、[#.?]

字符组的基本用法

[...]

preg_match('/[0123456]/', '5'); // => 1

preg_match('/[abc123]/', '5'); // => 0

范围表示法(range)

[x-y]表示x到y整个范围内的字符。如,[0123456789]表示为[0-9],[abcdefghijk]表示为[a-k]。

为什么是[0-9],而不是[9-0]?

因为-表示的范围一般是根据字符对应的码值(Code Point)来确定的。典型地有ACSⅡ编码。在ACSⅡ编码中,0~9的码值是48~57,a~z的码值是97~122,A~Z的码值是65~90。

preg_match('/[0-9]/', '5'); // => 1

preg_match('/[a-z]/', '5'); // => 0

preg_match('/[0-9a-fA-F]/', '0'); // 16进制

字符组简记法(shorthands)

提供比范围表示法更简洁的表示方法,如\d表示[0-9],\w表示[0-9a-zA-z_]。

php中支持的字符组简记:

\d 所有的数字,即[0-9]

\D 所有的非数字,与\d互斥

\w 所有的单词字符(字符、数字、下划线),即[0-9a-zA-Z_]

\W 所有的非单词字符,与\W互斥

\s 所有的空白字符,包括空格、制表符、回车符、换行符等空白字符

\S 所有的非空白字符,与\s互斥

preg_match('/\d/', '8'); // => 1

preg_match('/\d/', 'a'); // => 0

preg_match('/\d[a-z]/', 'a'); // => 1

preg_match('/\w/', 'a'); // => 1

preg_match('/\w/', '6'); // => 1

preg_match('/\w/', '_'); // => 1

preg_match('/\s/', ' '); // => 1

preg_match('/\s/', "\t"); // => 1

preg_match('/\s/', "\r"); // => 1

元字符与转义

在范围表示法中,字符组中的横线-不能匹配横线字符,而是用来表示范围,这类字符叫做元字符(meta-character)。元字符除了-还有开方括号[、闭刚括号]、^、$等,它们都有特殊的意义。

当元字符想要表示普通字符的含义时(如-就只想表示横线字符),就需要转义处理(在元字符前加反斜线字符\)。对于-,有一个例外情况,就是当它紧跟着字符组中的开括号[时,它就表示普通横线字符,此时不用转义。

preg_match('/[0\-9]/', "-"); // => 1

preg_match('/[0\-9]/', "8"); // => 0

preg_match('/[0\-9]/', "0"); // => 1

preg_match('/[-09]/', "-"); // => 1

preg_match("/[0\\-9]/", "-"); // => 1

preg_match("/[0\-9]/", "-"); // => 1

仔细看上面第一个表达式和最后两个表示式。这里要注意:

在php中,字符串既可以用单引号标注也可以用双引号标注。两者的主要区别在于,双引号字符串可以插值,二单引号字符串不能;另外,双引号字符串会处理字符串转义,二单引号字符串不会

正则表达式是以字符串的方式提供的。在php中,双引号字符串本身也有关于转义的规定(如"\\"、'\r'、"\t"等),因此"0\\-9"与'0\-9'是等价的。

那么最后一个表达式为什么也可以匹配呢?这是因为,尽管php的正则表达式用字符串文字给出,但它与常见的字符串不完全一样——如果某个转义序列可以有字符串识别,则对其进行转义处理;否则,将整个转义序列“原封不动”地保存下来。

因此,在正则表达式中转义要小心,在php中,使用单引号字符串来构建正则表达式会比双引号字符串更简单明了。

排除型字符组(Negated Character Class)

在方括号[…]中列出希望匹配的所有字符叫做“普通字符组”。在开方括号[之后紧跟一个脱字符^,写作[^…],表示“在当前位置,匹配一个没有列出的字符”。例如,[^0-9]匹配非数字字符。

preg_match('/[^0-9][0-9]/', "A8"); // => 1

排除型字符组中的紧跟着开方括号[的脱字符^也是元字符,如果要匹配尖括号字符,需要进行转义处理。但是,不紧跟着开方括号[的^就是普通字符,不需要转义。

preg_match('/[^0-9]/', '0'); // => 0

preg_match('/[\^0-9]/', '0'); // => 1

preg_match('/[\^0-9]/', '^'); // => 1

preg_match('/[0-9^]/', '^'); // => 1

POSIX字符组

之前介绍的字符组,都属于Perl衍生出来的正则表达式流派(Flavor),这个流派叫做PCRE(Per Compatible Regular Expression)。正则表达式还有其他流派,比如POSIX(Portable Operating System Interface for unix),它是一系列规范,定义了UNIX操作系统应当支持的功能,其中也包括了正则表达式的规范。

常见的[a-z]形式的字符组,在POSIX规范中仍然获得支持,称作POSIX方括号表达式。POSIX方括号表达式中的\不是用来转义的,如[\d]就只能匹配\和d两个字符。这里涉及到]、-这两个特殊字符,在POSIX规范中,紧接在开方括号[之后的]才表示闭方括号字符,紧挨在闭方括号]之前的-才表示横线字符。

对于PCRE规范中的\d、\w、\s等字符组简记法,POSIX中有类似的东西,叫做POSIX字符组。在ASCⅡ语言环境(locale)中,常见的POSIX字符组及其含义如下:

POSIX字符组

说明

ACSⅡ字符组

等价的PCRE简记法

[:alnum:]

字母和数字

[0-9a-zA-Z]

[:alpha:]

字母

[a-zA-Z]

[:ASCⅡ]

ASCⅡ字符

[\x00-\x7F]

[:blank:]

空格字符和制表字符

[ \t]

[:cntrl:]

控制字符

[\x00-\x1F\x7F]

[:digit:]

数字字符

[0-9]

\d

[:graph:]

空白字符之外的字符

[\x21-\x7E]

[:lower:]

小写字母字符

[a-z]

[:print:]

类似[:graph:],但包括空白字符

[\x20-\x7E]

[:punct:]

标点符号

[][!"#$%&'()*+,./:;<=>?@\^_`{\

}~-]

[:space:]

空白字符

[ \t\r\n\v\f]

\s

[:upper:]

大写字母

[A-Z]

[:word:]

字母字符

[A-Za-z0-9_]

\w

[:xdigit:]

十六进制字符

[A-Fa-f0-9]

php中有专门处理POSIX正则的函数,但从5.3.0开始已经废弃了。这里只是了解一下相关知识。

2. 量词

这里首先介绍一下^和$两个特殊字符,在上一章的元字符与转义一节提到过这两个特殊字符。

^放在正则表达式的开头,表示“定位到字符串的起始位置”;$用在正则表达式的末尾,表示“定位到字符串的结束位置”。

preg_match('/\w\d/', '1a2b'); // => 1

preg_match('/^\w\d/', '1a2b'); // => 0 必须以字母开头

preg_match('/\w\d$/', '1a2b'); // => 0 必须以数字结尾

preg_match('/^\w\d/', 'a2b'); // => 1

preg_match('/\w\d$/', '1a2'); // => 1

preg_match('/^\w\d$/', '1a2'); // => 0 开头必须是字母,结尾必须是数字

preg_match('/^\w\d$/', 'a2'); // => 1

量词的一般形式

如果要匹配一个邮政编码(6位数字),目前能写出来的正则表达式是^\d\d\d\d\d\d$:

preg_match('/^\d\d\d\d\d\d$/', '100010'); // => 1

preg_match('/^\d\d\d\d\d\d$/', '10001035'); // => 0

preg_match('/^\d\d\d\d\d\d$/', '10a010'); // => 0

\d重复6次的写法很不科学,正则表达式肯定会有更方便的写法,也就是量词(quantifier)。量词的通用形式是{m,n}(注意,,后面不能有空格),它限定之前的元素能够出现的次数,m是下限,n是上限。其他常见的量词形式有:

量词

说明

{n}

之前的元素必须出现n次

{m,n}

之前的元素最少出现m次,最多出现n次

{m,}

之前的元素最少出现m次,出现次数无上限

{0,n}

之前的元素可以不出现,也可以出现,最多出现n次

preg_match('/^\d{6}$/', '100010'); // => 1

preg_match('/^\d{4,6}$/', '123'); // => 0

preg_match('/^\d{4,6}$/', '1234'); // => 1

preg_match('/^\d{4,6}$/', '123456'); // => 1

preg_match('/^\d{4,6}$/', '1234567'); // => 0

常用量词

正则表达式还有三个常用的量词,分别是+、?、*:

常用量词

{m,n}等价形式

说明

*

{0,}

可能出现,也可能不出现,出现次数没有上限

+

{1,}

至少出现1次,出现次数没有上限

?

{0,1}

出现0次或1次

这三种量词在实际中使用的非常多。

例如,匹配url的时候,有可能是http,也有可能是https,这个时候用?就很方便:

preg_match('/^https?:\/\/www\.baidu\.com/', 'http://www.baidu.com'); // => 1

preg_match('/^https?:\/\/www\.baidu\.com/', 'https://www.baidu.com'); // => 1

在匹配html的tag(如

、等)的时候,在中间会有字符,但是字符长度不确定。这种情况下就需要使用+了:

preg_match('/^]+>$/', ''); // => 1

preg_match('/^]+>$/', ''); // => 1

preg_match('/^]+>$/', '<>'); // => 0

如果说匹配一个双引号字符串,在双引号内,既可以出现字符也可以不出现字符。这种情况下就应该使用量词*。

preg_match('/^\"[^\"]*\"$/', '""'); // => 1

preg_match('/^\"[^\"]*\"$/', '"abcd"'); // => 1

点号

点号.是与量词搭配比较多得一个字符。一般情况下,点号.可以匹配除了换行符\n以外的任意字符。

preg_match('/^.$/', 'z'); // => 1

preg_match('/^.$/', '8'); // => 1

preg_match('/^.$/', "\n"); // => 0

如果要使.能匹配的字符包含换行符\n,可以使用自制通配符\s\S或\w\W、\d\D。

preg_match('/^[\s\S]$/', "\n"); // => 1

使.能匹配的字符包含换行符\n的另外一种方法是指定正则匹配时使用单行模式。在php中,可以使用模式修饰符和预定义常量两种方法来指定单行模式。关于正则匹配的模式,后面会详细介绍。

preg_match('/(?s)^.$/', "\n"); // => 1 模式修饰符

preg_match('/^.$/s', "\n"); // => 1 预定义常量

匹配优先量词、忽略优先量词

很多语言中,都可以使用/*...*/来注释代码,如果是一个支持语法高亮的文本编辑器就要能够提取/*...*/注释块。很easy的,我们可以写出如下正则表达式:

$str = '/*this is a comment*/ /*this is another comment*/';

preg_match('/\/\*.*\*\//', $str, $arr);

echo $arr[0];

/*this is a comment*/ /*this is another comment*/

可以看到,这个正则表达式出了点小问题,它把两个注释块匹配出来了,如果两个注释块中间有代码,那么代码也会匹配出来。

这是因为,我们介绍的*、+、?都是匹配优先量词(greedy quantifier,也称贪婪量词)。匹配优先量词是指在拿不准是否要匹配的时候,优先尝试匹配。因此,$str中间的*/ /*都被.*匹配了。

正则表达式中利用忽略优先量词来解决上述问题。与*、+、?对应的忽略优先量词的形式是*?、+?、??。忽略优先量词在不确定是否要匹配时选择“不匹配”的状态。还是以提取注释块的代码为例:

preg_match('/\/\*.*?\*\//', $str, $arr);

echo $arr[0];

/*this is a comment*/

这样就达到了提取注释块的效果。

匹配优先量词

忽略优先量词

限定次数

*

*?

可能出现,可能不出现,出现次数没有上限

+

+?

至少出现1次,没有上限

?

??

出现0次或1次

{m,n}

{m,n}?

出现次数大于等于m,小于等于n

{m,}

{m,}?

至少出现m次,没有上限

{0,n}

{0,n}?

出现0次-n次

php中有指定非贪婪匹配模式的模式修饰符和预定义常量,与忽略优先量词是一样的效果:

// 默认贪婪匹配

preg_match('/\/\*.*\*\//', $str, $arr); // => /*this is a comment*/ /*this is another comment*/

// 预定义常量 指定非贪婪匹配

preg_match('/\/\*.*\*\//U', $str, $arr); // => /*this is a comment*/

// 模式修饰符 指定非贪婪匹配

preg_match('/(?U)\/\*.*\*\//', $str, $arr); // => /*this is a comment*/

// 同时使用 忽略优先量词 和 预定义常量

preg_match('/\/\*.*?\*\//U', $str, $arr); // => /*this is a comment*/ /*this is another comment*/

// 同时使用 忽略优先量词 和 模式修饰符

preg_match('/(?U)\/\*.*?\*\//', $str, $arr); // => /*this is a comment*/ /*this is another comment*/

量词的转义

*、+、?的转义比较简单,就是\*、\+、\?。主要是{m,n}形式的转义需要注意。

量词

转义

量词

转义

量词

转义

{n}

\\{n}

*

\*

*?

\*\?

{m,n}

\\{m,n}

+

\\+

+?

\\+\?

{m,}

\\{m,}

?

\?

??

\?\?

{0,n}

\\{0,n}

3.括号

分组

上一章介绍了量词,上一章的例子中量词都只能控制它前面的字符或字符组。那么量词能否控制连续的字符或字符组呢,如控制一个单词hello出现或者不出现。这就要用到正则表达式的分组功能(子表达式),使用圆括号(...)实现分组(子表达式)。

// 量词限定前面一个字符

preg_match('/^hello?, world$/', 'hello, world'); // => 1

preg_match('/^hello?, world$/', 'hell, world'); // => 1

preg_match('/^hello?, world$/', ', world'); // => 0

// 量词限定一个单词

preg_match('/^(hello)?, world$/', 'hello, world'); // => 1

preg_match('/^(hello)?, world$/', 'hell, world'); // => 0

preg_match('/^(hello)?, world$/', ', world'); // => 1

多选结构

多选结构(alternative)的形式是(...|...),在括号内以竖线|分开多个子表达式,这些子表达式也叫多选分支(option)。

例如,匹配常见的11位手机号

// 匹配常见11位手机号

preg_match('/(13[0-9]|15[0-356]|18[025-9])\d{8}/', '18521510001', $arr); // => 1

引用分组

正则表达式会保存每个(...)分组匹配的文本,这种功能叫捕获分组(capturing group)。在需要直接使用子表达式的时候非常有用

例如,提取标签中的地址和描述文本

// 提取标签中的地址和描述文本

preg_match('/(.*?)/', 'visit github', $arr);

print_r($arr);

/*

Array

(

[0] => github

[1] => github.com

[2] => visit github

)

*/

正则表达式替换时也支持捕获分组。php中支持\num和$num的形式替换,但是num不能大于10;另一种形式${num}可以大于10。

例如,日期的替换

// 正则表达式替换

preg_replace('/(\d{4})-(\d{2})-(\d{2})/', '$1年$2月$3日', '2015-08-25'); // => 2015年08月25日

preg_replace('/(\d{4})-(\d{2})-(\d{2})/', '\1年\2月\3日', '2015-08-25'); // => 2015年08月25日

反向引用

在正则表达式内部引用之前的捕获分组匹配的文本叫反向引用(back-reference)。实测php支持\num形式的反向引用,不支持$num形式的反向引用

例如,利用反向引用匹配id相同的不同标签

// 匹配id为main的标签

preg_match('/.*?/', '

hello, world
', $arr); // => 1

print_r($arr);

/*

Array

(

[0] =>

hello, world

[1] => div

)

*/

// 匹配id为main的标签

preg_match('/.*?/', '

Hello, World

', $arr); // => 1

print_r($arr);

/*

Array

(

[0] =>

Hello, World

[1] => p

)

*/

命名分组

数字编号的分组有时候不够直观,因此有些语言和工具的正则表达式提供了命名分组(named grouping)。

正则字符中(?P)来命名,(?P=name)来使用。preg_replace替换时不支持

// 捕获命名分组

preg_match('/[^\'"\s]*)">(?P.*?)/', '', $arr);

print_r($arr);

/*

Array

(

[0] => visit github

[link] => github.com

[1] => github.com

[description] => visit github

[2] => visit github

)

*/

// 反向引用命名分组

preg_match('/[\w]+)\s+id="main">.*?/', '

hello, world
', $arr);

print_r($arr);

/*

Array

(

[0] =>

hello, world

[tag] => div

[1] => div

)

*/

非捕获分组

正则表达式默认会保存每个(...)匹配的文本,前面利用这个特性可以实现一些有用的功能。但是,有时候正则表达式比较复杂,(...)会出现的比较多,而此时仅仅是想实现分组或者多选的功能,而不需要捕获分组;同时,大量不需要的捕获分组可能会影响性能。

为了解决这种问题,正则表达式提供了非捕获分组(non-capturing group),它的形式是(?:...)。

// 捕获分组

preg_match('/(13[0-9]|15[0-356]|18[025-9])\d{8}/', '18521510001', $arr); // => 1

print_r($arr);

/*

Array

(

[0] => 18521510001

[1] => 185

)

*/

// 非捕获分组

echo preg_match('/(?:13[0-9]|15[0-356]|18[025-9])\d{8}/', '18521510001', $arr); // => 1

print_r($arr);

/*

Array

(

[0] => 18521510001

)

*/

4.断言

正则表达式中的有些结构不匹配真正的文本,只负责判断在某个位置左/右侧的文本是否符合要求,这种结构称为断言(assertion)。常见的断言有三类:单词边界、行起始/结束位置、环视。

单词边界

单词边界(word boundary),记为\b。它匹配的是单词边界(一边是单词字符,另一边不是单词字符)的位置,而不是字符。

// 单词边界

preg_match('/\b\w+\b/', 'word', $arr); // => 1

print_r($arr);

/*

Array

(

[0] => word

)

*/

// 匹配所有单词边界

preg_match_all('/\b\w+\b/', 'hello, world', $arr); // => 2

print_r($arr);

/*

Array

(

[0] => Array

(

[0] => hello

[1] => world

)

)

*/

这类匹配位置而不匹配字符的元素叫做锚点(anchor),下一节要介绍的^、$等也是锚点。

行起始/结束位置

^:字符串的开始位置

$:字符串的结束位置

$str = 'first line

second line

last line';

// 字符串起始位置

preg_match_all('/^\w+\b/', $str, $arr); // => 1

print_r($arr);

/*

Array

(

[0] => Array

(

[0] => first

)

)

*/

// 字符串结束位置

preg_match_all('/\b\w+$/', $str, $arr); // => 1

print_r($arr);

/*

Array

(

[0] => Array

(

[0] => line

)

)

*/

如果指定了多行模式(Multiline Mode),^、$分别可以匹配行起始位置、行结束位置。关于模式,将在下一章详细介绍。指定多行模式的方式是使用模式修饰符(?m):在正则表达式之前加上(?m);或者是预定义常量的方式:/.../m 。

// 多行模式 行起始位置

// preg_match_all('/^\w+\b/m', $str, $arr); 是一样的效果

preg_match_all('/(?m)^\w+\b/', $str, $arr); // => 3

print_r($arr);

/*

Array

(

[0] => Array

(

[0] => first

[1] => second

[2] => last

)

)

*/

//多行模式 行结束位置

// preg_match_all('/\b\w+$/m', $str, $arr); 是一样的效果

preg_match_all('/(?m)\b\w+$/', $str, $arr); // => 3

print_r($arr);

/*

Array

(

[0] => Array

(

[0] => line

[1] => line

[2] => line

)

)

*/

\A不论是普通模式还是多行模式,都匹配字符串起始位置

\Z、\z不论是普通模式还是多行模式,都匹配字符串结束位置

\Z与\z的区别在于最后字符串的末尾是行终止符的时候,\Z匹配行终止符之前的位置,\z则不管行终止符,只匹配“整个字符串的结束位置”。

这里用行终止符,而不用换行符的原因是不同操作系统的行终止符不同(windows\r\n,linux\n,mac\n)。

bVp25z

bVp25A

// \A 始终匹配字符串起始位置

preg_match_all('/\A\w+\b/', $str, $arr); // => 1

print_r($arr);

/*

Array

(

[0] => Array

(

[0] => first

)

)

*/

preg_match_all('/(?m)\A\w+\b/', $str, $arr); // => 1

print_r($arr);

/*

Array

(

[0] => Array

(

[0] => first

)

)

*/

// \Z始终匹配行结束位置

preg_match_all('/\b\w+\Z/', $str, $arr); // => 1

print_r($arr);

/*

Array

(

[0] => Array

(

[0] => line

)

)

*/

preg_match_all('/(?m)\b\w+\Z/', $str, $arr); // => 1

print_r($arr);

/*

Array

(

[0] => Array

(

[0] => line

)

)

*/

// \Z \z的区别

$str = 'first line

second line

last line

';

preg_match_all('/(?m)\b\w+\z/', $str, $arr); // => 0

print_r($arr);

/*

Array

(

[0] => Array

(

)

)

*/

preg_match_all('/(?m)\b\w+\Z/', $str, $arr); // => 1

print_r($arr);

/*

Array

(

[0] => Array

(

[0] => line

)

)

*/

环视

环视(look-around)用来“停在原地,四处张望”,它本身也不匹配任何字符,用来限定它旁边的文本满足某种条件。

名字

记法

含义

肯定顺序环视

(?=...)

向右看看,右边出现了环视中的内容才匹配

否定顺序环视

(?!...)

向右看看,右边不出现环视中的内容才匹配

肯定逆序环视

(?<=...)

向左看看,左边出现了环视中的内容才匹配

否定逆序环视

(?

向左看看,左边不出现环视中的内容才匹配

例如,要匹配html标签中的开标签(、

、等),而不能匹配闭标签(、
、等)和自闭和标签(
等),同时,也不能匹配一个空的标签<>。

直接使用将/字符排除是不对的,因为有些标签的属性中可能会含有/字符。例如。这里只是在开尖括号之前的第一个字符不能为/。

然而]*[^\/]>也是不行的,因为在之间会至少匹配两个字符,像这样的标签是无法匹配到的。这里就要用到环视了。

上面的正则表达式中有两个环视结构,一个在开尖括号之前,表示在闭尖括号>之前向左看看,左边挨着的字符不能为/。

上面的正则表达式已经解决了匹配html中开标签的主要问题,只是其中的.*?还需要优化一下。需要解决的问题是:

有可能会有单引号'或双引号",它们都得成对出现

单引号对或双引号对之内可以有>字符,但是它们的外面不能有>字符

利用正则表达式的选择结构,可以写出下面的表达式,用于完善上面的问题。

])+(?

5.匹配模式

前面的内容中已经出现介过了单行模式、多行模式、非贪婪模式。匹配模式是指匹配时使用的规则。常用的匹配模式还有不区分大小写模式、注释模式。

在开始介绍具体的模式之前,先介绍php中模式的两种具体实现/.../{modifier}和...(?{modifier})...:

模式修饰符

/.../{modifier}

...(?{modifier})...

示例

/

.*/s(?s).*

名称(php手册)

模式修饰符

模式内修饰符

名称(《正则指引》)

预定义常量

模式修饰符

作用范围

整个正则表达式

不在分组(子表达式)中时,对它后面的全部正则表达式起作用;如果在分组(子表达式)中,则对它分组中的剩余部分起作用。在没有分组,且放在整个正则表达式最前面的时候相当于/.../{modifier}

支持程度

支持所有模式修饰符

支持部分模式修饰符

其他编程语言

可能不支持

一般都支持

不区分大小写模式

在html中是不区分大小写的,例如

和、、的作用是一样的。如果要从网页中提取,不使用匹配模式的表达式应该是这样:

由于

标签只有两个字符,所以上面的写法还可以接受。但是如果标签是world';

preg_match('/

.*<\/tr>/', $str, $arr);

print_r($arr);

/*

Array

(

[0] =>

helloworld

)

*/

// 非贪婪匹配模式

$str = '

helloworld';

preg_match('/

.*<\/tr>/U', $str, $arr);

print_r($arr);

/*

Array

(

[0] =>

hello

)

*/

Unicode

要匹配中文等Unicode字符,最好是指定Unicode模式修饰符/.../u。如果不指定会有两个问题

GBK编码环境下,中文不能匹配

无法利用[\x{4e00}-\x{9fff}]匹配中文

// 指定unicode模式

preg_match('/

[\x{4e00}-\x{9fff}]*<\/td>/u', '姚明', $arr);

print_r($arr);

/*

Array

(

[0] =>

姚明

)

*/

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值