目录

1. 常用正则表达式符号和特殊字符

?2.? Re 模块:核心函数和方法

2.1 re.compile() 编译函数

2.1.1?re.compile() 语法格式

2.1.2?re.compile() 用法

2.2 re.match() 和 re.search() 匹配和搜索函数

2.2.1?re.match() 语法格式

2.2.2?re.match() 用法

2.2.3?re.search() 语法格式

2.2.4?re.search() 用法

2.3 re.findall() 和 re.finditer() 查找所有符合条件的字符串

2.3.1?re.findall() 语法格式

2.3.2?re.findall() 用法

2.3.3?re.finditer() 语法格式

2.3.4?re.finditer() 用法

2.4 re.split() 分割函数

2.4.1?re.split() 语法结构

2.4.2?re.split() 用法

2.5 re.sub() 和 re.subn() 替换函数

2.5.1 re.sub() 语法结构

2.5.2 re.sub() 用法

2.5.3 re.subn() 语法结构

2.5.4 re.subn() 用法

3. 贪婪模式和非贪婪模式

4. 扩展表示法

4.1?(?iLmsux) 在正则表达式中嵌入一个或者多个特殊"标记"参数

4.1.1 (?i)

4.1.2 (?L)

4.1.3 (?m)

4.1.4 (?s)

4.1.5 (?u)

4.1.6 (?x)

4.2?(?:…) 表示一个匹配不用保存的分组

4.3?(?P…) 由名字 name 标示而不是数字 ID 表示的正则分组

4.3.1 使用数字 ID 表示分组

?4.3.2 使用名字 name?表示分组

4.4?(?P=name)? 在正则后面引用前面的组

4.5?(?#comments) 标示注释,所有内容都被忽略

4.6?(?=…) 正向前行匹配,以 …?字符串结尾才匹配

4.7?(?!..)?负向前行匹配,?不以 … 字符串结尾才匹配

4.8?(?<=…) 正向后行匹配,之前有 … 字符串才进行匹配

4.9?(<!..) 负向后行匹配,之前没有 … 字符串才进行匹配

4.10?(?(id/name)Y|N) 匹配不同的字符串


1. 常用正则表达式符号和特殊字符

正则表达式是处理数据时候经常用到的,背景不再赘述。简单说下 Python 中两种模式匹配。

第一种是搜索 searching,第二种是匹配 matching。

搜索即在字符串中任意部分搜索匹配的模式,而匹配是是指判断一个字符串能否从起始处全部或者部分的匹配某个模式。

搜索通过 Re.search() 实现,匹配通过 Re.match() 实现,Re 是 Python 内置的库。

现在来介绍最常用的元字符 ( metacharacter ) --特殊字符和符号,正是它们赋予了正则表达式强大的功能和灵活性。

正则表达式中最常见的符号

记号

说明

示范

普通字符串

就匹配该字符串的值

abc,123,A_B_2

re1|re2

匹配正则表达式 re1 或者 re2

abc|123,就是 abc 或者 123

.

匹配除了换行符之外的任何字符

a.b,意味着可以是abb,acb,a2b 等待

^

匹配字符串的开始

^abc,可以是abcd,abce,但是不能是babc

$

匹配字符串的结尾

ab$,可以是ab,cab,2ab, 但是不能是abc

*

匹配前面出现的正则表达式零次或者多次,该正则表达式可以是单个字符,也可以是()包起来的

a*,可以是aaaaa,或者空字符

(abc)*,可以是abcabcabc,或者空字符

匹配前面出现的正则表达式1次或者多次,该正则表达式可以是单个字符,也可以是()包起来的

a+,可以是aaaaa,或者a

(abc)+,可以是abcabcabc,或者abc

匹配前面出现的正则表达式零次或者1次,该正则表达式可以是单个字符,也可以是()包起来的

a,可以是a,或者空字符

(abc),可以是abc,或者空字符

{N}

匹配前面出现的正则表达式 N 次

a{4},即aaaa

{M,N}

匹配前面出现的正则表达式 M 到 N 次

a{2,4},即aa,aaa,aaaa

[…]

匹配字符组中出现的任何一个字符

[abc] ,即匹配a、b、c

[…X-Y…]

匹配从字符 X 到 Y 的任意字符

[0-3],即匹配0、1、2、3

[^…]

即不匹配此字符集中出现的任何一个字符

[^0-3],即匹配除了 0、1、2、3之外的所有字符

(*|+||{})

用于上面出现的任何“非贪婪”。版本重复匹配次数符号。

这个需要在讲贪婪模式的时候详细讲。

(…)

匹配封闭括号中正则表达式,并且保存在子组

在讲 re.search/match 等具体函数时候可以详细的讲。

以上都是正则表达式最最常用的,如果对上面不熟悉,后面的章节可以不看了。

正则表达式-特殊字符

记号

示范

示范

d

匹配任何数字,等同于[0-9],( D 是 d 的反义:非任何数字)

abcde,可以是abc0e、abc1e、abc2e 等

w

匹配任何数字字母字符,等同于[0-9a-zA-Z],( W 是 w 的反义:非任何数字字母字符)

_w,即_0…_9,_a…_z,_A…_Z 都可以

s

匹配任何空白符号,等同于[ ],(S 是 s 的反义字符)

absc,可以是"ab c"

匹配单词边界,(B 是 的反义字符)

The 意味着The,但是不能是 The 开头的字符串

n

匹配已经保存的子组(需要和(…)一起使用)

在讲 re.search/match 等具体函数时候可以详细的讲。

c

逐一匹配特殊字符c(即,取消它的特殊含义,按照字面上匹配)

如.,即匹配字符.

如 \,即匹配字符

A

匹配字符串的起始

Aabc

Z

匹配字符串结束,如果是存在换行,只匹配到换行前的结束字符串

abcZ

2. Re 模块:核心函数和方法

2.1 re.compile() 编译函数

re.compile 对正则表达式模式 pattern 进行编译,编译后的结果可以用于 re.search、re.match、re.findall 等函数,它并不是必须的,但是它非常有用!

为什么说不是必须的呢,请看下面的一段代码。可以看出,无论是直接用正则表达式还是编译后再使用,都可以得到一样的结果。

a="abc"
patt="^ab"
res=re.match(patt,a)
print(res.group())
patt=re.compile("^ab")
res=re.match(patt,a)
print(res.group())

那为什么还要有 re.compile() 这个函数呢,因为性能!

Python 的代码终究会被编译成字节码,然后才会被解释器执行,如果使用预编译代码会比使用字符串要快,并且我们处理文档时候,往往是一个正则表达式要用很多次,如果直接使用字符串,那么每次都需要重复编译,而直接采用预编译,然后调用预编译结果,则可以快很多。同一个正则表达式被使用得越多越划算。

希望大家养成这个良好的编程习惯!即使模块函数可能对已经编译的对象进行缓存,还是会节省了查询缓存和使用相同字符串反复调用函数的性能开销。

2.1.1re.compile() 语法格式

re.compile(pattern, flags=0)

pattern 即第一章中提到的正则表达式,flags是可选的,默认为 0。flags 的可选值如下:

  1. .re.I (re.IGNORECASE): 忽略大小写
  2. .re.M (MULTILINE): 多行模式,改变’^‘和’$'的行为
  3. .re.S (DOTALL): 点任意匹配模式,改变’.'的行为
  4. .re.L (LOCALE): 使预定字符类 w W B s S 取决于当前区域设定
  5. .re.U (UNICODE): 使预定字符类 w W B s S d D 取决于unicode定义的字符属性
  6. .re.X (VERBOSE): 详细模式。这个模式下正则表达式可以是多行,忽略空白字符,并可以加入

上述 flag 可以单独用,也可以一起使用。

2.1.2re.compile() 用法

在上一个代码段中就已经显示了,后续也会反复使用,此处不再赘述。

2.2 re.match() 和 re.search() 匹配和搜索函数

2.2.1re.match() 语法格式

re.match(pattern, string, flags=0)

flags 和re.compile() 中的 flags 用法一致。

string 即被匹配的字符串。

2.2.2re.match() 用法

用一小段代码来演示,match 是从字符串的开始进行匹配的。

#匹配全体Python整型的字符串表示形式的集合
patt=re.compile("^[0-9]+$")
words=["1","23","09","www.XXX.net","8.0","a2","_d3234","cd"]
for word in words:if(re.match(patt,word)):print(word)

2.2.3re.search() 语法格式

re.search(pattern, string, flags=0)

flags 和re.compile() 中的 flags 用法一致。

string 即被匹配的字符串。

2.2.4re.search() 用法

请注意,search 只找到第一个符合条件字符串的就返回了,所以即使被搜索的字符串中还有其他的符合字符串,也被忽略了。

请注意,此处 match 也好,search 也好,都是返回的一个对象,这个对象有方法 group(),groups(),如果没有找到的时候,返回的是 None 对象。

group() 方法或者返回所有匹配对象,或者是根据特定要求返回某个特定子组。

groups() 方法很简单,它返回一个包含唯一或者所有子组的元组,如果正则表达式中没有子组的话,groups() 将返回一个空元组,而 group() 则仍然返回全部匹配对象。

下面是一个没有子组的代码( 没有使用()来划分子组 )。

# 找出字符串中中包含的 ab 字符串,不区分大小
a="S abc ABC -sfg- dfghdfh abc AB A ABCD ED BA ab Ab aB sgwet"
patt=re.compile("AB",re.I)
res=re.search(patt,a)
print(res.group()) #请注意,此处只找到第一个符合条件的就返回了
print(res.groups())

这是一个有子组的代码,使用了 (),可以看到 group() 返回了全部匹配对象,而 groups() 则返回各自的子组。

# 找出字符串中中包含的 abcde 字符串,不区分大小
a="S abc ABC -sfg- dfghdfh abc AB A ABCDE ED BA ab Ab aB sgwet"
patt=re.compile("(AB)c(DE)",re.I)
res=re.search(patt,a)
print(res.group()) #请注意,此处只找到第一个符合条件的就返回了
print(res.groups())

另外,返回对象中可能有用的 .start() 和 .end() 方法,返回匹配对象起始地址和截止地址。

words=["abcom"]
patt=re.compile("^abcom")
for word in words:res=re.search(patt,word)if(res is not None):print(res) # 返回的是一个 re.Match 对象print(res.group()) # 返回全部匹配对象print(res.groups()) # 返回子组,如果有的话,没有则返回空()print(res.start()) #返回匹配对象起始地址print(res.end()) #返回匹配对象截至地址

2.3 re.findall() 和 re.finditer() 查找所有符合条件的字符串

2.3.1re.findall() 语法格式

re.findall(pattern, string, flags=0)
flags 和re.compile() 中的 flags 用法一致。
string 即被匹配的字符串。

2.3.2re.findall() 用法

re.findall 可以查找出所有的符合要求的字符串,并且返回一个列表

下面这段代码描述了四种常见的情况。

# 找出字符串中中包含的 abcde 字符串,不区分大小
a="S abc ABC -sfg- dfghdfh abc AB A ABCDE ED BABcdedf ab Ab aB sgwet"
#没有子组
patt=re.compile("ABcDE",re.I)
res=re.findall(patt,a)
# 请注意,此处没有 group()、groups() 对象,因为返回的是列表。
# 因为没有子组,返回的是全部对象的列表
print(res)  #此处有子组
patt=re.compile("(AB)c(DE)",re.I)
res=re.findall(patt,a)
# 请注意,此处没有 group()、groups() 对象,因为返回的是列表。
# 因为有子组,返回的包含子组元组的列表,而不是全部对象的列表
print(res)  #此处有子组,并且把整个字符串用()包括起来了
patt=re.compile("((AB)c(DE))",re.I)
res=re.findall(patt,a)
# 请注意,此处没有 group()、groups() 对象,因为返回的是列表。
# 因为有子组,且把整个字符串用()包括起来了
#所以返回的包含全部匹配对象、各个子组元组的列表,而不是全部对象的列表
print(res)  #此处有子组,子组里面还有子组,并且把整个字符串用()包括起来了
patt=re.compile("((A(B))c(DE))",re.I)
res=re.findall(patt,a)
# 请注意,此处没有 group()、groups() 对象,因为返回的是列表。
# 因为有子组,且把整个字符串用()包括起来了
#所以返回的包含全部匹配对象、各个子组元组的列表,而不是全部对象的列表
print(res)

2.3.3re.finditer() 语法格式

re.finditer(pattern, string, flags=0)
flags 和re.compile() 中的 flags 用法一致。
string 即被匹配的字符串。

re.finditer() 和re.findall() 非常相似,只不过返回的是一个迭代器,而不是列表,对于每个匹配返回一个匹配对象(re.match 匹配对象)。所以读取方式有了变化,这样内存会更加友好。

2.3.4re.finditer() 用法

将 re.findall 函数的用法处代码稍微改一下。

# 找出字符串中中包含的 abcde 字符串,不区分大小
a="S abc ABC -sfg- dfghdfh abc AB A ABCDE ED BABcdedf ab Ab aB sgwet"
#没有子组
patt=re.compile("ABcDE",re.I)
res=re.finditer(patt,a)
# 请注意,此处没有 group()、groups() 对象,因为返回的是列表。
# 因为没有子组,返回的是全部对象的迭代器
print("*"*28)
for tmp in res:print(tmp)print(tmp.group())print(tmp.groups())#此处有子组
patt=re.compile("(AB)c(DE)",re.I)
res=re.finditer(patt,a)
# 请注意,此处没有 group()、groups() 对象,因为返回的是迭代器。
# 因为有子组,返回的包含子组元组的迭代器,而不是全部对象的迭代器
print("*"*28)
for tmp in res:print(tmp)print(tmp.group())print(tmp.groups())#此处有子组,并且把整个字符串用()包括起来了
patt=re.compile("((AB)c(DE))",re.I)
res=re.finditer(patt,a)
# 请注意,此处没有 group()、groups() 对象,因为返回的是迭代器。
# 因为有子组,且把整个字符串用()包括起来了
#所以返回的包含全部匹配对象、各个子组元组的迭代器,而不是全部对象的迭代器
print("*"*28)
for tmp in res:print(tmp)print(tmp.group())print(tmp.groups())#此处有子组,子组里面还有子组,并且把整个字符串用()包括起来了
patt=re.compile("((A(B))c(DE))",re.I)
res=re.finditer(patt,a)
# 请注意,此处没有 group()、groups() 对象,因为返回的是迭代器。
# 因为有子组,且把整个字符串用()包括起来了
#所以返回的包含全部匹配对象、各个子组元组的迭代器,而不是全部对象的迭代器
print("*"*28)
for tmp in res:print(tmp)  print(tmp.group())print(tmp.groups())

2.4 re.split() 分割函数

大家肯定用过 str.split(), re.split()功能更加强大,因为它被设计出来时候就是可以使用正则表达式的。

2.4.1re.split() 语法结构

re.split(pattern, string, maxsplit=0, flags=0)

flags 和re.compile() 中的 flags 用法一致。
string 即被匹配的字符串。

maxsplit 是最多能被分割的次数,从左而右计算。

re.split() 返回一个列表。

2.4.2re.split() 用法

可以看到下面这段代码,虽然剩下的代码还可以分割,但是因为限制了分割的次数,也不再分割。

a="das:fgfd:dfdgf:dadf"
res=re.split(":",a,2)
res

2.5 re.sub() 和 re.subn() 替换函数

2.5.1 re.sub() 语法结构

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

flags 和re.compile() 中的 flags 用法一致。

repl 即用来替换的字符串

string 即被替换的字符串。

count 即被替换的次数,为 0 时候意味着全部替换。

re.sub()返回被替换后的字符串

2.5.2 re.sub() 用法

# 找出字符串中中包含的 ab 字符串,不区分大小,并且用 XY 来替换
a="S abc ABC -sfg- dfghdfh abc AB A ABCDE ED BABcdedf ab Ab aB sgwet"
#没有子组
patt=re.compile("AB",re.I)
res=re.sub(patt,"XY",a)
# 请注意,此处返回的是字符串
print(res)

2.5.3 re.subn() 语法结构

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

flags 和re.compile() 中的 flags 用法一致。

repl 即用来替换的字符串

string 即被替换的字符串。

count 即被替换的次数,为 0 时候意味着全部替换。

re.sub()返回一个元组,第一个元素是被替换后的字符串,第二个元素是被替换次数的数值。

2.5.4 re.subn() 用法

# 找出字符串中中包含的 ab 字符串,不区分大小,并且用 XY 来替换
a="S abc ABC -sfg- dfghdfh abc AB A ABCDE ED BABcdedf ab Ab aB sgwet"
#没有子组
patt=re.compile("AB",re.I)
res=re.subn(patt,"XY",a)
# 请注意,此处返回的是字符串和替换次数的列表
print(res)

3. 贪婪模式和非贪婪模式

给大家看下面一小段代码,想在一串字符串中找出连续的数字字符,1 个或者多个都可以。结果是找出了最长的那个符合要求的。这就是贪心匹配,也叫贪婪模式,Python 中默认的模式,在从左到右的顺序中求值时候,尽可能的抓取满足匹配的最长的字符。

在使用"*","+",或者"?" 取长度不确定的字符串时候,都会遇到这种情况。

# 找出连续的数字字符,1 个或者多个
a="0123456789"
patt=re.compile("d+")
res=re.search(patt,a)
# 请注意,此处返回的是匹配对象
print(res)
print(res.group())
print(res.groups())

如果不想要贪婪模式,只要最短的满足条件的字符串,可以在"*","+",或者"?"后面使用 “?” 来使用非贪婪模式。

4. 扩展表示法

4.1(iLmsux) 在正则表达式中嵌入一个或者多个特殊"标记"参数

之前在说re.compile 、re.match、re.search 等函数,提到了模型 pattern 里面配套使用的 flags。其实,除了re.compile 、re.match、re.search函数中使用 flags 选项,还可以直接在正则表达式中使用类似的功能,即扩展表达式。常见的有(iLmsux),下面会一一慢慢说。

首先请注意,(iLmsux) 只能在正则表达式的开头使用;并且**(imx) 正则表达式包含三种可选标志:i, m, 或 x ,只影响括号中的区域;(-imx) 正则表达式关闭 i, m, 或 x 可选标志。只影响括号中的区域。**

4.1.1 (i)

首先,(i) 表示 re.I/IGNORECASE,忽略大小写;

words=["abcom","abco","abCoMD","ABCOM","BDAbcOM"]
#patt=re.compile("(?iabcom)")
for word in words:res=re.search(r"(?i)abcom",word)if(res is not None):print("*"*20)print(word)print(res.group())print(res.groups())

4.1.2 (L)

等同re.l,re.LOCALE, 表示字符集本地化。即使预定字符类 w W B s S 取决于当前区域设定 。

这个功能是为了支持多语言版本的字符集使用环境的,比如在转义符w,在英文环境下,它代表[a-zA-Z0-9_],即所以英文字符和数字。如果在一个法语环境下使用,缺省设置下,不能匹配"é" 或 “”。加上这L选项和就可以匹配了。不过这个不适用于中文环境,将会在第五小节讲如何匹配中文字符。

4.1.3 (m)

等同于 re.M ,即多行模式;

word='''
This line is the first abcom,
another line ABCOM,
that line, it's the bestABcomm
'''res=re.findall(r"(?im)(^th[ws]+)",word)
if(res is not None):print(res)

4.1.4 (s)

表示符号 . 可以代表任意符号(正常情况符号 . 表示除 之外的任意符号);等同于.re.S (DOTALL)。用下面的代码,就可以清晰的看出使用 (s) 和不使用直接的差异了。

word='''
This line is the first abcom,
another line ABCOM,
that line, it's the bestABcomm
'''res=re.findall(r"(?is)(th.*)",word)
if(res is not None):print(res)
res=re.findall(r"(?i)(th.*)",word)
if(res is not None):print(res)

4.1.5 (u)

等同re.U,re.UNICODE,使用 w, W, , B 这些元字符时将按照 UNICODE 定义的属性.

4.1.6 (x)

等同于 re.X ,冗长模式,允许编写更友好的正则表达式。

4.2(:…) 表示一个匹配不用保存的分组

用下面这段代码来看,当使用 re.search 函数时候,如果使用了 (:…) 语法,那么返回的对象使用 .groups() 方法时候,则不会体现那个子组。

word="I am happy now, let's have a happy day! If you are not happy, please do not tell me!"res = re.search(r'(?:happy)sw{3,4}', word)
if(res is not None):print("*"*40)print(res)print(res.group())print(res.groups())print(res.groups(1))res = re.search(r'(happy)sw{3,4}', word)
if(res is not None):print("*"*40)print(res)print(res.group())print(res.groups())print(res.groups(1))

再看一个复杂一点的例子

当不使用 (

Python 正则表达式使用--Re 模块详解相关推荐

  1. Python之ruamel.yaml模块详解(三)| ruamel.yaml与pyyaml的区别

    Python之ruamel.yaml模块详解(三)| ruamel.yaml与pyyaml的区别 12 默认支持Yaml1.2 13 Py2和Py3重新整合 14 修复 15 测试 16 API 接前 ...

  2. Python正则表达式re.sub功能详解

    Python正则表达式re.sub功能详解 正则表达式:regular expression, 缩写为re;  sub即substitute(替换) ; re.sub 语法结构: re.sub (pa ...

  3. python中 xlrd/xlwt模块详解

    python中 xlrd/xlwt模块详解 1.什么是xlrd模块 python操作excel主要用到xlrd和xlwt两个库,即xlrd是读excel,xlwt是写excel库 一.安装xlrd模块 ...

  4. python之sys模块详解_(转)python之os,sys模块详解

    python之sys模块详解 原文:http://www.cnblogs.com/cherishry/p/5725184.html sys模块功能多,我们这里介绍一些比较实用的功能,相信你会喜欢的,和 ...

  5. python正则表达式处理txt,python 正则表达式参数替换实例详解 python使用正则表达式替换txt内容...

    Python正则表达式如何进行字符串替换实例 import res = 'adds23dd56'ss = re.sub(r'\d', '*', s)>>> ss'adds**dd** ...

  6. python re模块详解_python与正则表达式:re模块详解

    re模块是python中处理正在表达式的一个模块 正则表达式知识储备:http://www.cnblogs.com/huamingao/p/6031411.html 1. match(pattern, ...

  7. python中的findall函数_关于Python正则表达式 findall函数问题详解

    在写正则表达式的时候总会遇到不少的问题, 特别是在表达式有多个元组的时候.下面看下re模块下的findall()函数和多个表达式元组相遇的时候会出现什么样的坑. 代码如下: import re str ...

  8. 刻意练习:Python基础 -- Task13. datetime模块详解

    datetime模块 datetime 是 Python 中处理日期的标准模块,它提供了 4 种对日期和时间进行处理的类:datetime.date.time 和 timedelta. datetim ...

  9. python Logging日志记录模块详解

    写在篇前   logging是Python的一个标准库,其中定义的函数和类为应用程序和库的开发实现了一个灵活的事件日志系统.Python logging 的配置由四个部分组成:Logger.Handl ...

最新文章

  1. Google 全球员工围攻 Google!
  2. Opencv实战之图像的基本操作:这效果出来惊艳了众人(附代码解析)
  3. linux查看密码配置文件,如何在Linux上查看和配置密码时效
  4. Educational Codeforces Round 76 (Rated for Div. 2) E. The Contest 思维 + 差分
  5. 从SAP客户主数据里直接创建商机(Opportunity) 1
  6. 【Java数据结构与算法】第一章 稀疏数组和队列
  7. UIWebView捕获内部web点击事件
  8. python可以嵌在vba中吗_Jupyter Notebooks嵌入Excel并使用Python替代VBA宏
  9. Sitadel:一款功能强大的Web应用扫描器
  10. BFS宽度优先搜索(新冠病毒的传播)
  11. linux下安装了lxml但依然报错rom lxml import etreeModuleNotFoundError: No module named ‘lxml‘
  12. 2020科大讯飞iFLYTEK A.I.开发者大赛
  13. 必要转载 1927年12月31日午夜一秒谜案
  14. ras私钥c#转java_C#和JAVA的RSA密钥、公钥转换
  15. Vue.js学习笔记—调查问卷WebApp
  16. jqury ajax 直接获取数据库信息,使用jQuery Ajax从数据库加载信息
  17. H5+CSS实现三级菜单(包括水平、垂直菜单和网页架构)
  18. java 中文转成_Java将中文转换成unicode字符。
  19. [18调剂]华侨大学(厦门校区)田晖教授招收2018级计算机或相近专业调剂生
  20. 一万个bug——安装阿里云SDK核心库遇到的问题(涉及Rust、cryptography、openssl等的安装)

热门文章

  1. 岗位竞聘机制如何引入?
  2. java动态时钟_Java实现的动态数字时钟功能示例【显示世界时间】|chu
  3. 步进电机基础(7.1)-步进电机的选择方法-电机种类的选择(各种步进电机的优缺点)
  4. 浅谈---免费ARP 【Gratuitous ARP】
  5. 一个有意思的github项目“狗屁不通文章生成器”
  6. #考研笔记#计算机问答题
  7. 比top更优秀的htop
  8. sqlyog企业版 v8.32注册码
  9. C++ 读文件某一行(特定行)数据
  10. 对标AVAX,下一个百倍币MXT!