shell编程之正则表达式

正则表达式的概述

正则表达式,又称正规表达式、常规表达式

正则表达式的定义:

正则表达式是使用单个字符串来描述、匹配一系列符合某个句法规则的字符串简单来说,是一种匹配字符串的方法,通过一些特殊符号,实现快速查找、删除、替换某个特定字符串。
正则表达式是由普通字符与元字符组成的文字模式。其中普通字符包括大小写字母、数字、标点符号及一些其他符号,元字符则是指那些在正则表达式中具有特殊意义的专用字符,可以用来规定其前导字符(即位于元字符前面的字符)在自标对象中的出现模式。

正则表达式的用途

正则表达式对于系统管理员来说是非常重要的,系统运行过程中会产生大量的信息,这些信息有些是非常重要的,有些则仅是告知的信息。身为系统管理员如果直接看这么多的信息数据,无法快速定位到重要的信息,如“用户账号登录失败”“服务启动失败”等信息。这时可以通过正则表达式快速提取“有问题”的信息。如此一来,可以将运维工作变得更加简单、方便。

正则表达式的分类

正则表达式的字符串表达方法根据不同的严谨程度与功能分为基本正则表达式与扩展正则表达式。基础正则表达式是常用正则表达式最基础的部分。在 Linux系统中常见的文件处理工具中 grep与 sed支持基础正则表达式,而egrep 与awk 支持扩展正则表达式。

正则表达式层次

●基础正则表达式
●扩展正则表达式

Linux中文本处理工具

grep (基础正则表达式)
egrep(扩展正则表达式)
sed (基础正则表达式)
awk (扩展正则表达式)

基础正则表达式元字符

基础正则表达式是常用的正则表达式部分
除了普通字符外,常见到以下元字符
\:转义字符(使具有特殊意义的元字符作为普通字符去使用 )
例:!、\n(换行)等
^:匹配字符串开始的位置
例:a、the、^#
: 匹 配 字 符 串 结 束 的 位 置 例 : w o r d :匹配字符串结束的位置 例: word ::word
.:匹配除\n之外的任意的一个字符
例: go.d、g…d
:匹配前面子表达式0次或者多次
例: goo
d、go.*d
[list]:匹配list列表中的一个字符
例: go[ola]d,[abc]、[a-z]、[a-z0-9]
[^list]:匹配任意不在list列表中的一个字符
例:[a-z]、[0-9]、[^A-Z0-9]
{n,m}:匹配前面的子表达式n到m次,有{n}、{n,}、{n,m}三种格式
例: go{21}d、go{2,31}d、go{2,l}d
基础正则表达式

gerp应用

grep的使用规则:

-n:表示显示行号
-i:表示不区分大小写
-v:表示反向过滤
[ ]:查找集合字符

用法示例

创建测试用的txt文件

vi test.txt
he was short and fat.
He was wearing a blue polo shirt with black pants.
The home of Football on BBC Sport online.
the tongue is boneless but it breaks bones.12!
google is the best tools for search keyword.
The year ahead will test our political establishment to the limit.
PI=3.141592653589793238462643383249901429.
a wood cross!
Actions speak louder than words.
#woood#
#woooooood#

AxyzxyzxyzxyzC
l bet this place is really spooky late at night!
Misfortunes never come alone/single.
l shouldn't have lett so tast.

匹配文章中有the的行并显示行号

[root@server3 ~]# grep -n 'the' test.txt

若反向选择,如查找不包含“the”字符的行,则需要通过grep命令的“-v选项实现,并配合“-n”一起使用显示行号。
//反向过滤包含the的行,并显示行号(匹配不包含the的行,并显示行号)

[root@server3 ~]# grep -vn 'the' test.txt

利用中括号“[]”来查找集合字符说“[io]”表示匹配“i”或者“o”

[root@server3 ~]# grep -n 'sh[oi]rt' test.txt 

查找包含重复单个字符“oo”时,只需要执行以下命令即可。

[root@server3 ~]# grep -n 'oo' test.txt

若查找“oo”前面不是“w”的字符串,只需要通过集合字符的反向选择“[^]”来实现该目的。
例如执行“grep -n’[^w]oo’ test.txt”命令表示在 test.txt 文本中查找“oo”前面不是“w”的字符串。

[root@server3 ~]# grep -n '[^w]oo' test.txt

若不希望“oo”前面存在小写字母,可以使用“grep -n ‘[ ^a-z]oo’ test.txt”命今实现

[root@server3 ~]# grep -n '[^a-z]oo' test.txt

查找包含数字的行可以通过“grep -n ‘[0-9]’ test.txt”命令来实现。

[root@server3 ~]# grep -n '[0-9]' test.txt

查找行首"^“与行尾字符”$"

[root@server3 ~]# grep -n '^the' test.txt

查询大写字母开头的行则使用“1”规则

[root@server3 ~]# grep -n '^[A-Z]' test.txt

查询不以字母开头的行则使用[a-z A-Z]”规则

root@server3 ~]# grep -n '^[^a-zA-Z]' test.txt

小数点(.)在正则表达式中也是一个元字符,所以在这里需要用转义字符“\”将具有特殊意义的字符转化成普通字符
//匹配以“.”结尾的

[root@server3 ~]# grep -n '\.$' test.txt

查询空白行时,执行“grep -n‘^$’test.txt”命令

[root@server3 ~]# grep -n '^$' test.txt

正则表达式中小数点(.)也是一个元字符,代表任意一个字符

[root@server3 ~]# grep -n 'w..d' test.txt

若想要查询oo、ooo、ooooo 等资料,则需要使用星号()元字符。但需要注意的是,“”代表的是重复零个或多个前面的单字符。“o*”表示拥有零个(即为空字符)或大于等于一个“o”的字符,因为允许空字符,所以执行“grep -n 'o*’ test.txt”命令会将文本中所有的内容都输出打印。如果是“oo*”,则第一个o 必须存在,第二 个o则是零个或多个o,所以凡是包含o、oo、ooo、ooo,等的资料都符合标准。同理,若查询包含至少两个o以上的字符串,则执行“grep -n ‘ooo*’ test.txt”命令即可。
匹配包含2个oo以上的

[root@server3 ~]# grep -n 'ooo*' test.txt

查询以w开头d结尾,中间包含至少一个o 的字符串

[root@server3 ~]# grep -n 'woo*d' test.txt

执行以下命令即可查询以w开头d 结尾,中间的字符可有可无的字符串。

[root@server3 ~]# grep -n 'w.*d' test.txt

可以配备包含0-9的,也可以是包含0-9以为的两位数等数字

[root@server3 ~]# grep -n '[0-9][0-9]*' test.txt

查找连续字符范围“{}”
因为“{}”在 Shell 中具有特殊意义,所以在使用“{}”字符时,需要利用转义字符“\”,将“{}”字符转换成普通字符。
1)查询两个o 的字符。

[root@server3 ~]# grep -n 'o\{2\}' test.txt

2)查询以w开头以d结尾,中间包含2~5个o 的字符串。

[root@server3 ~]# grep -n 'wo\{2,5\}d' test.txt

3)查询以w开头以d 结尾,中间包含2个或2个以上o 的字符串。

[root@server3 ~]# grep -n 'wo\{2,\}d' test.txt

基础正则表达式-元字符总结

匹配输入字符串的开始位置。除非在方括号表达式中使用,表示不包含该字符集合。要匹配“”字符本身,请使用“^” 匹 配 输 入 字 符 串 的 结 尾 位 置 。 如 果 设 置 了 R e g E x p ( 正 则 表 达 式 ) 对 象 的 M u l t i l i n e 属 性 , 则 “ 匹配输入字符串的结尾位置。如果设置了RegExp(正则表达式)对象的Multiline属性,则“ RegExp()Multiline”也匹配‘\n’或‘\r’
要匹配“$”字符本身,请使用"$"
.匹配除“\r\n”(都是换行)之外的任何单个字符
\反斜杠,又叫转义字符,去除其后紧跟的元字符或通配符的特殊意义
匹配前面的子表达式零次或多次。要匹配“”字符,请使用“*”
[]字符集合。匹配所包含的任意一个字符。例如,“[abc]”可以匹配“plain”中的“a”
[]赋值字符集合。匹配未包含的一个任意字符。例如,“[abc]”可以匹配“plain”中任何一个字母
[n1-n2]字符范围。匹配指定范围内的任意一个字符。例如,“[a-z]”可以匹配“a”到“z”范围内的任意一个小写字母字符。
注意:只有连字符(-)在字符组内部,并且出现在两个字符之间时,才能表示字符的范围;如果出现在字符组的开头,则只能表示连字符本身
{n} 中n是一个非负整数,匹配确定的n次。例如,“o{2}”不能匹配“Bob”中的“o”,但是能匹配“food”中的“oo”
{n,}中n是一个非负整数,至少匹配 n次。例如,“o{2,}”不能匹配“Bob”中的“o”,但能匹配“foooood”中的所有o。“o{1,}”等价于“o+”。“o{0,}”则等价手“o*”
{n, m} m和n均为非负整数,其中 n<=m,最少匹配n 次且最多匹配m 次

sed应用

定义

sed (Stream EDitor)是一个强大而简单的文本解析转换工具,可以读取文本,并根据指定的条件对文本内容进行编辑(删除替换,添加,移动等),最后输出所有行或者仅输出处理的某些行。

工作流程

1.读取:sed 从输入流(文件,管道,标准输入)中读取一行内容并存储到临时的缓存区中(又称模式空间,pattern space)。

2.执行:默认情况下。所有的sed命令都在模式空间中顺序地执行,除非指定了行的地址,否则sed命令将会在所有的行上依次执行。

3.显示:发送修改后的内容到输出流。在发送数据后,模式空间将会被清空。

在所有的文件内容都被处理完成之前,上述过程将重复执行,直至所有内容被处理完。

注意:默认情况下所有的sed命令都是在模式空间内执行的,由此输入的文件并不会发生任何变化,除非是用重定向存储输出。

sed命令常见用法

sed   [选项]  ‘操作’  参数
sed   [选项]  -f   scriptfile  参数

常见是sed命令选项主要包含以下几种

-e script(脚本命令) : 指定sed编辑命令
-f scriptfile(文件) : 指定的文件中是sed编辑命令
-h 或 --help :显示帮助
-n,–quiet 或 silent :表示仅显示处理后的结果
-i :直接编辑文本文件(会对文件产生变化)

常见的操作包括以下几种

a: 增加,在当前行下面增加一行指定内容
c:替换,将选定行替换为指定内容
d:删除,删除选定的行
i:插入,在选定行上面插入一行指定内容
p:打印,如果同时指定行,表示打印指定行;如果不指定行,则表示打印所有内容;如果有非打印字符,则以ASCII码输出。其通常与“-n”选项一起使用。(输出)
s:替换,替换指定字符
y:字符转换

用法示例

输出文件内容

1.带行号输出所有内容 等同于 cat test.txt

[root@server2 ~]# nl test.txt | sed -n 'p'

2.输出第4行,或者3到5行

[root@server2 ~]# nl test.txt | sed -n '4p'
[root@server2 ~]# nl test.txt | sed -n '3,5p

3.输出偶数行;奇数行

[root@server2 ~]# nl test.txt | sed -n 'n;p'
[root@server2 ~]# nl test.txt | sed -n 'p;n'

4.输出1到6行之间的偶数行,3到9行之间的奇数行

[root@server2 ~]# nl test.txt | sed -n '1,6{n;p}'
[root@server2 ~]# nl test.txt | sed -n '3,9{p;n}'

5.输出以第6行到结尾之间的偶数行(即以第6行为起始行,重新排序设置)

[root@server2 ~]# nl test.txt | sed -n '6,${n;p}'

6.输出包含the的内容

[root@server2 ~]# sed -n '/the/p' test.txt

输出从第3行开始到第一个包含the的行(是一个区间过程)

[root@server2 ~]# nl test.txt | sed -n '3,/the/p' 

8.输出包含the的所在行的行号(等号用来输出行号)

[root@server2 ~]# sed -n '/the/=' test.txt

9.输出以PI为开头的内容;以0到9数字为结尾的内容

[root@server2 ~]# sed -n '/^PI/p' test.txt
[root@server2 ~]# sed -n '/[0-9]$/p' test.txt

10.输出包含单词home的行(<> 代表单词边界)

[root@server2 ~]# sed -n '/\<home\>/p' test.txt
[root@server2 ~]# grep 'home' test.txt 

删除符合条件的文本

nl :命令用于计算文件的行数
1.删除第5行;删除2到4行

[root@server2 ~]# nl test.txt | sed '5d'
[root@server2 ~]# nl test.txt | sed '2,4d'

2.删除除了包含单词home的内容的其它所有行

[root@server2 ~]# nl test.txt | sed '/home/!d'
     3	The home of Football on BBC Sport online.

3.删除以a-z小写字母为开头的内容
[root@server2 ~]# sed ‘/2/d’ test.txt

4.删除以.为结尾的内容

[root@server2 ~]#  sed '/\.$/d' test.txt 

5.删除所有空行

[root@server2 ~]#  sed '/^$/d' test.txt 

替换符合条件的文本

使用sed命令进行替换操作时需要用到s(字符串替换),c(整行/整块替换),y(字符替换)命令选项

1.将每行中的第一个the替换为THE

[root@server2 ~]# sed 's/the/THE/' test.txt 

2.将文件中的所有the替换为THE

[root@server2 ~]# sed 's/the/THE/g' test.txt 

3.将每行中的第2个l替换为L

[root@server2 ~]# sed 's/l/L/2' test.txt 

4.将文件中的所有的o删除(替换为空串)

[root@server2 ~]# sed 's/o//g' test.txt 

5.在每行行首插入#号

[root@server2 ~]# sed 's/^/#/' test.txt 

6.在每行行尾插入字符串EOF

[root@server2 ~]# sed 's/$/EOF/' test.txt 

7.在包含the的每行行首插入#号

[root@server2 ~]# sed '/the/s/^/#/' test.txt 

8.将包含the的所有行中的o替换为O

[root@server2 ~]# sed '/the/s/o/O/g' test.txt 

迁移符合条件的文本

在使用sed命令迁移符合条件的文本时,常用到以下参数
H:复制到剪切板
g,G :将剪切板中的数据覆盖/追加至指定行
w:保存为文件
r:读取指定文件
a:追加指定内容
1.将包含the的行迁移至文件末尾,{;}用于多个操作

[root@server2 ~]# sed '/the/{H;d};$G' test.txt

2.将第1-4行内容转移至第16行后

[root@server2 ~]# sed '1,4{H;d};16G' test.txt

3.将包含the的行另存为文件out.file

[root@server2 ~]# sed '/the/w out.file' test.txt 
[root@server2 ~]# ls -lh
[root@server2 ~]# cat out.file 

4.将文件/etc/hostname的内容添加到包含the的每行以后

[root@server2 ~]# sed '/the/r /etc/hostname' test.txt 

5.在第三行前面插入一个新行,内容为New

[root@server2 ~]# sed '3iNew' test.txt

6.在包含the的每行后插入一个新行,内容为New

[root@server2 ~]# sed '/the/aNew' test.txt 

7.在文件最后结尾后插入一个新行,内容为New

[root@server2 ~]# sed '$aNew' test.txt 

8.在第三行后插入一个新行,内容为New1,后换行插入一个新行,内容为new2
(中间的\n表示换行)

[root@server2 ~]# sed '4aNew1\nnew2' test.txt 

注意:\n 和\r的区别:
\n 换行符,是另起一新行(光标换行)
\r 回车符,光标回到一旧行的开头(覆盖前一个)

使用脚本编辑文件

使用sed脚本将多个编辑指令存放到文件中(每行一条编辑指令),通过“-f”选项来调用

[root@server2 ~]# vi opt.list
[root@server2 ~]# sed -f opt.list test.txt 

1,5H   1到5行剪切
1,5d   1到5行删除
17G     17行追加

sed直接操作文件示例

编写一个脚本,用来调整vsftpd 服务配置,要求禁止匿名用户,但允许本地用户(也允许写入)。
在服务器是创建本地用户

[root@server2 ~]# useradd dada
[root@server2 ~]# passwd dada
[root@server2 ~]# useradd xiaoxiao
[root@server2 ~]# passwd xiaoxiao
[root@server2 ~]# vi ftp.sh                        编辑脚本
[root@server2 ~]# chmod +x ftp.sh
[root@server2 ~]# ./ftp.sh                         运行脚本

在客户机上安装ftp进行访问

#!/bin/bash
A=vsftpd
FTP=/etc/vsftpd/vsftpd.conf
yum -y install $A
sed -i -e '/local_enable/s/NO/YES/g' $FTP
sed -i -e '/write_enable/s/NO/YES/g' $FTP
sed -i -e 's/^#chroot_local_user=YES/chroot_local_user=YES/g' $FTP
sed -i  '$aallow_writeable_chroot=YES' $FTP
sed -i -e '/listen/s/NO/YES/g' $FTP
sed -i -e '/listen_ipv6/s/YES/NO/g' $FTP
systemctl start $A
netstat -anpt | grep $A
[root@server1 ~]# yum -y install ftp
[root@server1 ~]# ftp 20.0.0.11
Name (20.0.0.11:root): dada
ftp> exit
[root@server1 ~]# ftp 20.0.0.11
Name (20.0.0.11:root): xiaoxiao
ftp> exit

扩展正则表达式

扩展正则表达式元字符

扩展正则表达式是对基础正则表达式的扩充深化

扩展元字符

+:匹配前面子表达式1次以上
例如:go+d,将匹配至少一个o(如god,good,goood…)

?:匹配前面子表达式0次或者1次
例如:go?d,将匹配gd或god

():括号中的字符串作为一个整体
例如:(xyz)+,将匹配xyz整体1次以上,如xyzxyz

|:以或的方式匹配字条串
例如1:good|food,将匹配good或者food
例如2:g(oo|la)d,将匹配good或者glad
(g|f)ood good或者food

egrep

用法示例:
1.匹配o至少出现一次或者以上次数的内容

[root@server2 ~]# vi test.txt 
[root@server2 ~]# grep -n 'oo*' test.txt 
[root@server2 ~]# egrep -n 'o+' test.txt 

2.匹配以be为开头,t为结尾,中间可以是s或者为空的内容

[root@server2 ~]# egrep -n 'bes?t' test.txt 

3.匹配以sh为开头,rt为结尾,中间可以是i或者o的内容

[root@server2 ~]# grep -n sh[io]rt test.txt 
[root@server2 ~]# egrep -n 'sh(i|o)rt' test.txt 
[root@server2 ~]# egrep -n sh'(i|o)'rt test.txt 

4.匹配包含oo出现一次,或者一次以上的内容

[root@server2 ~]# egrep -n '(oo)+' test.txt 

awk工具介绍

功能强大的编辑工具
无交互的情况下实现复杂的文本操作

命令格式

awk 选项 ‘模式或条件 {编辑指令}’ 文件1 文件2
awk -f 脚本文件 文件1 文件2

解析

awk是一个功能强大的编辑工具,逐行读取输入文本,并根据指定的匹配模式进行查找,对符合条件的内容进行格式化输出或者过滤处理,可以在无交互的情况下实现相当复杂的文本操作,被广泛应用于Shell脚本,完成各种自动化配置任务。

[root@server2 ~]# cat /etc/passwd  用户账号文件(保存用户名称,宿主目录,登录shell等基本信息)
 zjq:x:1000:1000:zjq:/home/zjq:/bin/bash
zjq:用户账号
x : 密码占位
1000:用户账号ID
1000:组账户ID
zjq:用户说明
/home/zjq:宿主目录
/bin/bash:登录shell

用法示例

1.查找出在/etc/passwd所有文件信息的第1个,第7个字段内容

[root@server2 ~]# awk -F: '{print $1,$7}' /etc/passwd

2.查找出在/etc/passwd所有文件信息的第1个,第7个字段内容且以zjq为开头的和以/sbin/nologin结尾的内容

[root@server2 ~]# awk -F: '/^zjq/{print $1,$7}' /etc/passwd
[root@server2 ~]# awk -F: '/\/sbin\/nologin$/{print $1,$7}' 

内建变量

awk 包含几个特殊的内建变量(可直接用)如下所示:
FS:指定每行文本的字段分隔符,默认为空格或制表位。
NF:当前处理的行的字段个数。
NR:当前处理的行的行号(序数)。
$0: 当前处理的行的整行内容。
$n:当前处理的行的第n个字段(第n列)。
FILENAME:被处理的文件名
RS:数据记录分隔,默认为\n,即每行为一条记录

用法示例

1.输出第3行的第1第7个字段

[root@server2 ~]# awk -F: 'NR==3{print $1,$7}' /etc/passwd

2.输出第3行到第6行的第1第7个字段
输出第3行,第6行的第1第7个字段
输出大于等于第3行小于等于第6行的第1第7个字段

[root@server2 ~]# awk -F: 'NR==3,NR==6{print $1,$7}' /etc/passwd
[root@server2 ~]# awk -F: '(NR==3)||(NR==6){print $1,$7}' /etc/passwd
[root@server2 ~]# awk -F: '(NR>=3)&&(NR<=6){print $1,$7}' /etc/passwd

3 输出奇数行,偶数行的行号

[root@server2 ~]# cat /etc/passwd | wc -l 
[root@server2 ~]# awk -F: '(NR%2)==1{print $1,$7}' /etc/passwd | wc -l
[root@server2 ~]# awk -F: '(NR%2)==0{print $1,$7}' /etc/passwd | wc -l

4.统计以/bin/bash为结尾的行数

[root@server2 ~]# awk  'BEGIN {x=0};/\/bin\/bash$/{x++};END {print x}' /etc/passwd

按字段输出文本

1.输出文件中每行中(以空格或制表符分隔)的第三个字段

[root@server2 ~]# awk '{print $3}' test.txt 

2.输出文件中每行中(以空格或制表符分隔)的第一和三个字段

[root@server2 ~]# awk '{print $1,$3}' test.txt 

3.输出没有设置密码的用户

[root@server2 ~]# awk -F: '$2=="!!"{print}' /etc/shadow 
[root@server2 ~]# awk  'BEGIN {FS=":"};$2=="!!"{print}' /etc/shadow 

4.输出第7字段包含/bash,/bin/bash的用户

[root@server2 ~]# awk -F: '$7~"/bash"{print $1}' /etc/passwd
[root@server2 ~]# awk -F: '$7~"/bin/bash"{print $1}' /etc/passwd

5.输出在/etc/services中第一个字段是nfs的且字段数是4个

[root@server2 ~]# grep "nfs" /etc/services
[root@server2 ~]# awk '($1~"nfs")&&(NF==4){print $1}' /etc/services

6.输出第7字段不是/bin/bash也不是/sbin/nologin的内容

[root@server2 ~]# awk -F: '($7!="/bin/bash")&&($7!="/sbin/nologin"){print}' /etc/passwd

通过管道,双引号调用Shell命令

.1.调用wc -l命令并用来统计1以/bash为结尾的行数即用户数

[root@server2 ~]# awk -F: '/bash$/{print}' /etc/passwd | wc -l
[root@server2 ~]# awk -F: '/bash$/{print | "wc -l"}' /etc/passwd 
[root@server2 ~]# grep -c "bash$" /etc/passwd

2.调用w命令统计在线的用户数

[root@server2 ~]# awk 'BEGIN {while ("w" | getline) n++; {print n-2}}'

3.调用hostname并输出当前的主机名

[root@server2 ~]# awk 'BEGIN {"hostname" | getline;print $0}' 

4.输出path变量中的值,第三个字段的值

[root@server2 ~]# echo $PATH
[root@server2 ~]# echo "$PATH" > a.txt
[root@server2 ~]# cat a.txt 
[root@server2 ~]# awk -F: '{print}' a.txt
[root@server2 ~]# awk -F: '{print$3}' a.txt

awk内置变量

FS:指定每行文本的字段分隔符,缺省为空格或制表位
NF:当前处理的行的字段个数
NR:当前处理的行的行号(序数)
$0:当前处理的行的整行内容
$n:当前处理行的第n个字段(第n列)

awk用法示例

按行输出文本
按字段输出文本
通过管道,双引号调用Shell命令


  1. A-Z ↩︎

  2. a-z ↩︎

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值