shell编程之正则表达式与文件处理器

前言

1.正则表达式是什么?2.文件处理器有几个?

1.正则表达式

正则表达式定义
正则表达式,又称正规表达式、常规表达式
使用字符串来描述、匹配一系列符合某个规则的字符串
正则表达式组成
◆普通字符
大小写字母、数字、标点符号及一些其他符号
◆元字符
在正则表达式中具有特殊意义的专用字符

正则表达式,又称规则表达式。(英语:Regular Expression),在代
码中常简写为 regex、regexp 或 RE),计算机科学的一个概念。正则表达式通常被用来检索、替换那些符合某个模
式(规则)的文本。
正则表达式不只有一种,而且 LINUX 中不同的程序可能会使用不同的正则表达式,如:
工具: grep sed awk egrep 


正则表达式---通常用于判断语句中,用来检查某一字符串是否满足某一格式
正则表达式是由普通字符与元字符组成
普通字符包括大小写字母、数字、标点符号及一些其他符号
元字符是指在正则表达式中具有特殊意义的专用字符,可以用来规定其前导字符(即位于元字符前面的字符)在目标对象中的出现模式


LINUX 中常用的有两种正则表达式引擎
基础正则表达式:BRE
扩展正则表达式: ERE

2.grep

grep 

-a :将 binary 文件以 text 文件的方式搜寻数据
-c :计算找到 '搜寻字符串' 的次数
-i :忽略大小写的不同,所以大小写视为相同
-n :顺便输出行号
-v :反向选择,亦即显示出没有 '搜寻字符串' 内容的那一行!
--color=auto :可以将找到的关键词部分加上颜色的显示喔!

基础正则表达式常见元字符:(支持的工具:grep、egrep、sed、awk)
特殊字符
\:转义符,将特殊字符进行转义,忽略其特殊意义a\.b匹配a.b,但不能匹配ajb,.被转义为特殊意义\\\\
^:匹配行首,^则是匹配字符串的开始^tux匹配以tux开头的行^^^^
$:匹配行尾,$则是匹配字符串的结尾tux$匹配以tux结尾的行$$$$ 
.:匹配除换行符\n之外的任意单个字符,awk则中可以ab.匹配abc或bad,不可匹配abcd或abde,只能匹配单字符....
[list]:匹配list列表中的一个字符 例: go[ola]d,[abc][a-z][a-z0-9]
[^list]:匹配任意不在list列表中的一个字符 例: [^a-z][^0-9][^A-Z0-9]
*:匹配前面子表达式0次或者多次 例:goo*d、go.*d
\{n\} :匹配前面的子表达式n次,例:go\{2\}d、'[O-9]\{2\}'匹配两位数字
\{n,\}:匹配前面的子表达式不少于n次,例: go\{2,\}d、' [0-9]\{2,\}'匹配两位及两位以上数宁
\{n,m\}﹔匹配前面的子表达式n到m次,例: go\{2,3\)d、'[0-9]\{2,3\}'匹配两位到三位数字
注: egrep、awk使用{n}{n, }{n, m}匹配时“{}"前不用加"\egrep -E -n 'wo{2}d' test.txt
egrep -E -n 'wo{2,3}d' test.txt

定位符
^ 匹配输入字符串开始的位置
$ 匹配输入字符串结尾的位置

非打印字符
\n 匹配一个换行符
\r 匹配一个回车符
\t 匹配一个制表符

扩展正则表达式(支持的工具:egrep、awk)
+	作用:重复一个或者一个以上的前一个字符
示例:执行“egrep -n 'wo+d' test.txt”命令,即可查询"wood" "woood" "woooooood"等字符串

?	作用:零个或者一个的前一个字符
示例:执行“egrep -n 'bes?t' test.txt”命令,即可查询“bet”“best”这两个字符串

|	作用:使用或者(or)的方式找出多个字符
示例:执行“egrep -n 'of|is|on' test.txt”命令即可查询"of"或者"if"或者"on"字符串

()	作用:查找“组”字符串
示例:“egrep -n 't(a|e)st' test.txt”。“tast”与“test”因为这两个单词的“t”与“st”是重复的,所以将“a”与“e”
列于“()”符号当中,并以“|”分隔,即可查询"tast"或者"test"字符串

()+	作用:辨别多个重复的组
示例:“egrep -n 'A(xyz)+C' test.txt”。该命令是查询开头的"A"结尾是"C",中间有一个以上的"xyz"字符串的意思

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3. sed 工具概述

1)文本处理工具,读取文本内容,根据指定的条件进行处理,如删除、替换、添加等
2)可在无交互的情况下实现相当复杂的文本处理操作
3)被广泛应用于Shell脚本,以完成自动化处理任务
4)sed依赖于正则表达式
sed(Stream EDitor)是一个强大而简单的文本解析转换工具,可以读取文本,并根据指定的条件对文本内容进行编辑(删除、替换、添加、移动等),最后输出所有行或者仅输出处理的某些行。sed 也可以在无交互的情况下实现相当复杂的文本处理操作,被广泛应用于 Shell 脚本中,用以完成各种自动化处理任务。
sed 的工作流程主要包括读取、执行和显示三个过程。
读取:sed 从输入流(文件、管道、标准输入)中读取一行内容并存储到临时的缓冲区中(又称模式空间,pattern space)。
执行:默认情况下,所有的 sed 命令都在模式空间中顺序地执行,除非指定了行的地址,否则 sed 命令将会在所有的行上依次执行。
显示:发送修改后的内容到输出流。在发送数据后,模式空间将会被清空。
在所有的文件内容都被处理完成之前,上述过程将重复执行,直至所有内容被处理完。


注意:默认情况下所有的 sed 命令都是在模式空间内执行的,因此输入的文件并不会发生任何变化,除非是用重定向存储输出。
1.sed 命令常见用法
通常情况下调用 sed 命令有两种格式,如下所示。其中,“参数”是指操作的目标文件, 当存在多个操作对象时用,文件之间用逗号“,”分隔;而 scriptfile 表示脚本文件,需要用“-f” 选项指定,当脚本文件出现在目标文件之前时,表示通过指定的脚本文件来处理输入的目标文件。

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


常见的 sed 命令选项主要包含以下几种。
-e 或--expression=:表示用指定命令或者脚本来处理输入的文本文件。
-f 或--file=:表示用指定的脚本文件来处理输入的文本文件。
-h 或--help:显示帮助。
-n、--quiet 或 silent:表示仅显示处理后的结果。
-i:直接编辑文本文件。

“操作”用于指定对文件操作的动作行为,也就是 sed 的命令。通常情况下是采用的“[n1[,n2]]”操作参数的格式。n1、n2 是可选的,代表选择进行操作的行数,如操作需要在 520 行之间进行,则表示为“5,20 动作行为”。常见的操作包括以下几种。
a:增加,在当前行下面增加一行指定内容。
c:替换,将选定行替换为指定内容。
d:删除,删除选定的行。
i:插入,在选定行上面插入一行指定内容。
p:打印,如果同时指定行,表示打印指定行;如果不指定行,则表示打印所有内容;如果有非打印字符,则以 ASCII 码输出。其通常与“-n”选项一起使用。
s:替换,替换指定字符。
y:字符转换。

2.用法示例
在本小节中依旧以 test.txt 文件为例进行演示。
(1)输出符合条件的文本(p 表示正常输出)


[root@localhost ~]# sed -n 'p' 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.
……//省略部分内容


//输出所有内容,等同于 cat test.txt

[root@localhost ~]# sed -n '3p' test.txt	//输出第 3 行
The home of Football on BBC Sport online.
[root@localhost ~]# sed -n '3,5p' test.txt	//输出 3~5 行
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.
[root@localhost ~]# sed -n 'p;n' test.txt	//输出所有奇数行,n 表示读入下一行资料
he was short and fat.
The home of Football on BBC Sport online. google is the best tools for search keyword.
……//省略部分内容
[root@localhost ~]# sed -n 'n;p' test.txt	//输出所有偶数行,n 表示读入下一行资料
He was wearing a blue polo shirt with black pants. the tongue is boneless but it breaks bones.12!
The year ahead will test our political establishment to the limit.

……//省略部分内容
[root@localhost ~]# sed -n '1,5{p;n}' test.txt //输出第 1~5 行之间的奇数行(第 1、3、5 行) he was short and fat.
The home of Football on BBC Sport online. google is the best tools for search keyword.
[root@localhost ~]# sed -n '10,${n;p}' test.txt	//输出第 10 行至文件尾之间的偶数行
#woood # AxyzxyzxyzxyzC
Misfortunes never come alone/single.


在执行“sed -n‘10,${n;p}’test.txt”命令时,读取的第 1 行是文件的第 10 行,读取的第 2
行是文件的第 11 行,依此类推,所以输出的偶数行是文件的第 11 行、13 行直至文件结尾, 其中包括空行。

以上是 sed 命令的基本用法,sed 命令结合正则表达式时,格式略有不同,正则表达式以“/”包围。例如,以下操作是 sed 命令与正则表达式结合使用的示例。

[root@localhost ~]# sed -n '/the/p' test.txt	//输出包含the 的行
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.
[root@localhost ~]# sed -n '4,/the/p' test.txt	//输出从第 4 行至第一个包含 the 的行
the tongue is boneless but it breaks bones.12! google is the best tools for search keyword.
 [root@localhost ~]# sed -n '/the/=' test.txt
//输出包含the 的行所在的行号,等号(=)用来输出行号
4
5
6
[root@localhost ~]# sed -n '/^PI/p' test.txt	//输出以PI 开头的行
PI=3.141592653589793238462643383249901429
[root@localhost ~]# sed -n '/[0-9]$/p' test.txt	//输出以数字结尾的行PI=3.141592653589793238462643383249901429
[root@localhost ~]# sed -n '/\<wood\>/p' test.txt
//输出包含单词wood 的行,\<\>代表单词边界
a wood cross!

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.1迁移符合条件的文本

在使用 sed 命令迁移符合条件的文本时,常用到以下参数.

H:复制到剪贴板;
g、G:将剪贴板中的数据覆盖/追加至指定行;
w:保存为文件;
r:读取指定文件;
a:追加指定内容。具体操作方法如下所示。

sed '/the/{H;d};$G' test.txt	//将包含the 的行迁移至文件末尾,{;}用于多个操作
sed '1,5{H;d};17G' test.txt	//将第 1~5 行内容转移至第 17 行后
sed '/the/w out.file' test.txt	//将包含the 的行另存为文件 out.file
sed '/the/r /etc/hostname' test.txt	//将文件/etc/hostname 的内容添加到包含 the 的每行以后
sed '3aNew' test.txt	//在第 3 行后插入一个新行,内容为New
sed '/the/aNew' test.txt	//在包含the 的每行后插入一个新行,内容为 New
sed '3aNew1\nNew2' test.txt	//在第 3 行后插入多行内容,中间的\n 表示换行

3.2使用脚本编辑文件

使用 sed 脚本将多个编辑指令存放到文件中(每行一条编辑指令),通过“-f”选项来调用。例如执行以下命令即可将第 1~5 行内容转移至第 16 行后。

sed ‘1,5{H;d};16G’ test.txt //将第 1~5 行内容转移至第 16 行后

以上操作可以改用脚本文件方式:

[root@localhost ~]# vi opt.list
1,5H
1,5d
17G
[root@localhost ~]# sed -f opt.list test.txt
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
I bet this place is really spooky late at night! Misfortunes never come alone/single.
I shouldn't have lett so tast.


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.

|| 表示上一条命令执行失败后,才执行下一条命令

3.3sed直接操作文件示例

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

 vim local_only_ftp.sh
#!/bin/bash
#指定样本文件路径、配置文件路径
SAMPLE="/usr/share/doc/vsftpd-3.0.2/EXAMPLE/INTERNET_SITE/vsftpd.conf " CONFIG="/etc/vsftpd/vsftpd.conf"
#备份原来的配置文件,检测文件名为/etc/vsftpd/vsftpd.conf.bak 备份文件是否存在, 若不存在则使用 cp 命令进行文件备份
[ ! -e "$CONFIG.bak" ] && cp $CONFIG $CONFIG.bak # 基于样本配置进行调整,覆盖现有文件
sed -e '/^anonymous_enable/s/YES/NO/g' $SAMPLE > $CONFIG

sed -i -e '/^local_enable/s/NO/YES/g' -e '/^write_enable/s/NO/YES/g' $CONFIG 
grep "listen" $CONFIG || sed -i '$alisten=YES' $CONFIG
#启动vsftpd 服务,并设为开机后自动运行
systemctl restart vsftpd systemctl enable vsftpd
[root@localhost ~]# chmod +x local_only_ftp.sh

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

4.awk工具

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

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

4.1awk工作原理

逐行读取文本,默认以空格为分隔符进行分隔,将分隔所得的各个字段保存到内建变量中,并按模式或者条件执行编辑命令

4.2awk内置变量

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

4.3awk用法示例

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

4.4概述

AWK 是一种处理文本文件的语言,是一个强大的文本分析工具。
它是专门为文本处理设计的编程语言,也是行处理软件,通常用于扫描、过滤、统计汇总工作
数据可以来自标准输入也可以是管道或文件
20世纪70年代诞生于贝尔实验室,现在centos7用的是gawk

之所以叫 AWK 是因为其取了三位创始人 Alfred Aho,Peter Weinberger, 和 Brian Kernighan 的 Family Name 的首字符。

工作原理:	
当读到第一行时,匹配条件,然后执行指定动作,再接着读取第二行数据处理,不会默认输出
如果没有定义匹配条件默认是匹配所有数据行,awk隐含循环,条件匹配多少次动作就会执行多少次

工作原理:
逐行读取文本,默认以空格或tab键为分隔符进行分隔,将分隔所得的各个字段保存到内建变量中,并按模式或者条件执行编辑命令。
sed命令常用于一整行的处理,而awk比较倾向于将一行分成多个""字段"然后再进行处理。awk信息的读入也是逐行读取的,执行结果可以通过print的功能将字段数据打印显示。在使用awk命令的过程中,可以使用逻辑操作符" &"表示""、"||表示"或""!"表示非";还可以进行简单的数学运算,如+、一、*、/、%、^分别表示加、减、乘、除、取余和乘方。

在这里插入图片描述
在这里插入图片描述

4.5其他BEGIN

 awk 'BEGIN{x=0};/\/bin\/bash$/ {x++;print x,$0};END {print x}' /etc/passwd
#统计以/ bin/bash结尾的行数,等同于
grep -c "/bin/bash$" /etc/passwd
BEGIN模式表示,在处理指定的文本之前,需要先执行BEGIN模式中指定的动作; awk再处理指定的文本,之后再执行END模式中指定的动作,END{}语句块中,往往会放入打印结果等语句

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

4.6getline

awk 'BEGIN { "hostname" | getline ; {print $0}}'#调用hostname,并输出当前的主机名
当getline左右无重定向符"<""I"时,awk首先读取到了第一行,就是1,然后getline,就得到了1下面的第二行,就是2,因为getline之后,awk会改变对应的NE,NR,FNR和$O等内部变量,所以此时的$O的值就不再是1,而是2了,然后将它打印出来。
当getline左右有重定向符"<""I"时,getline则作用于定向输入文件,由于该文件是刚打开,
并没有被awk读入一行,只是getline读入,那么getline返回的是该文件的第一行,而不是隔行。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

脚本编写

#!/bin/ bash
x=`awk '/Failed /{ip[$11]++}END{for(i in ip){print i","ip[i]}}' /var/log/secure`
#190.168.80.13 3
for j in $x
do
ip=`echo $j | awk -F "," '{print $1}'`
num=`echo $j | awk -F "," '{print $2}'`
if [ $num -ge 3 ];then
echo "警告! $ip访问本机失败了$num次,请速速处理!"
fi
done

5.小工具cut、sort、uniq、tr

cut:列截取工具
使用说明:

cut 命令从文件的每一行剪切字节、字符和字段并将这些字节、字符和字段写至标准输出。

如果不指定 File 参数,cut 命令将读取标准输入。必须指定 -b、-c 或 -f 标志之一

选项:
-b:按字节截取
-c:按字符截取,常用于中文
-d:指定以什么为分隔符截取,默认为制表符
-f:通常和-d一起

[root@localhost ~]# cat /etc/passwd | cut -d':' -f 1
root
bin
daemon

[root@localhost ~]# cat /etc/passwd | cut -d':' -f 3
0
1
2

[root@localhost ~]# cat /etc/passwd | cut -d':' -f1,3
root:0
bin:1
daemon:2

[root@localhost ~]# cat /etc/passwd | cut -d':' -f1-3
root:x:0
bin:x:1
daemon:x:2

[root@localhost ~]# who | cut -b 3
o
o
o
[root@localhost ~]# who | cut -c 3
o
o
o

[root@localhost ~]# cat name | cut -b 2
 
 
[root@localhost ~]# cat name | cut -c 2
刚
春

注意:cut只擅长于处理单个字符为间隔的文本

sort
是一个以行为单位对文件内容进行排序的工具,也可以根据不同的数据类型来排序。例如数据和字符的排序就不一样
语法:
sort [选项] 参数

常用选项
-t:指定分隔符,默认使用[Tab]键或空格分隔
-k:指定排序区域,哪个区间排序
-n:按照数字进行排序,默认是以文字形式排序
-u:等同于 uniq,表示相同的数据仅显示一行,注意:如果行尾有空格去重就不成功
-r:反向排序,默认是升序,-r就是降序
-o:将排序后的结果转存至指定文件

sort passwd.txt    //不加任何选项默认按第一列升序,字母的话就是从a到z由上而下显示

sort -n -t: -k3 passwd.txt    //以冒号为分隔符,以数字大小对第三列排序(升序)

sort -nr -t: -k3 passwd.txt   //以冒号为分隔符,以数字大小对第三列排序(降序)

sort -nr -t: -k3 passwd.txt -o passwd.bak    //将输结果不在屏幕上输出而是输出到passwd.bak文件

sort -u passwd.txt    //去掉文件中重复的行(重复的行可以是不连续的)
zhangsan
zhangsan
zhangsan
gggggg
lisi

uniq
主要用于去除连续的重复行
注意:是连续的行,所以通常和sort结合使用先排序使之变成连续的行再执行去重操作,否则不连续的重复行他不能去重

(1)语法
uniq [选项] 参数

(2)常用选项
-c:对重复的行进行计数;
-d:仅显示重复行;
-u:仅显示出现一次的行

[root@localhost ~]# cat fruit  //创建一个水果类型的文件,一共9行内容
apple
apple
peache
pear
banana
cherry
cherry
banana
orange

[root@localhost ~]# cat fruit | uniq -c    //统计重复行的次数,不连续的重复行他不算做重复行
      2 apple
      1 peache
      1 pear
      1 banana
      2 cherry
      1 banana
      1 orange

[root@localhost ~]# cat fruit | sort | uniq -c   //结合sort使用就是我们想要的效果
      2 apple
      2 banana
      2 cherry
      1 orange
      1 peache
      1 pear


[root@localhost ~]# cat fruit | sort | uniq -d   //结合sort使用,过滤出重复行
apple
banana
cherry


[root@localhost ~]# cat fruit | sort | uniq -u    //结合sort使用,过滤出不重复的行
orange
peache
pear

[root@localhost ~]# cat fruit | sort | uniq      //结合sort使用,去重
apple
banana
cherry
orange
peache
pear


[root@localhost ~]# cat fruit | sort -u     //也可以直接用sort -u
apple	
banana
cherry
orange
peache
pear


实例1:查看登陆用户
[root@localhost ~]# who
root     :0           2021-04-29 00:09 (:0)
root     pts/0        2021-04-29 00:09 (:0)
root     pts/1        2021-06-10 01:32 (192.168.245.1)
[root@localhost ~]# who | awk '{print $1}'
root
root
root
[root@localhost ~]# who | awk '{print $1}'| uniq
root

实例2:查看登陆过系统的用户
[root@localhost ~]# last | awk '{print $1}' | sort | uniq | grep -v "^$" | grep -v wtmp
reboot
root
shengjie

tr:它可以用一个字符来替换另一个字符,或者可以完全除去一些字符,也可以用它来除去重复字符

语法
用法:tr [选项]… SET1 [SET2]
从标准输入中替换、缩减和/或删除字符,并将结果写到标准输出。

常用选项
-d 删除字符
-s 删除所有重复出现的字符,只保留第一个

[root@localhost ~]# cat fruit | tr 'a-z' 'A-Z'
APPLE
APPLE
PEACHE
PEAR
BANANA
CHERRY
CHERRY
BANANA
ORANGE

[root@localhost ~]# cat fruit | tr 'apple' 'APPLE'    //替换是一一对应的字母的替换
APPLE
APPLE
PEAchE
PEAr
bAnAnA
chErry
chErry
bAnAnA
orAngE


[root@localhost ~]# cat fruit | tr 'a' ' '   //把替换的字符用单引号引起来,包括特殊字符
 pple
 pple
pe che
pe r
b n n 
cherry
cherry
b n n 
or nge


[root@localhost ~]# cat fruit | tr 'a' '/'      
/pple
/pple
pe/che
pe/r
b/n/n/
cherry
cherry
b/n/n/
or/nge

[root@localhost ~]# cat fruit | tr 'ap' '/'    //多个字符替换成一个
///le
///le
/e/che
/e/r
b/n/n/
cherry
cherry
b/n/n/
or/nge

[root@localhost ~]# cat fruit | tr 'apple' 'star'    //a替换成s,p替换成a,le替换成r
saarr
saarr
arschr
arsr
bsnsns
chrrry
chrrry
bsnsns
'orsngr'

[root@localhost ~]# cat fruit | tr "'" '/'     //如果想替换单引号则需要用双引号把单引号引起来,反斜杠转义也不行
apple
apple
peache
pear
banana
cherry
cherry
banana
/orange/

[root@localhost ~]# cat fruit | tr -d 'a'    //删除所有a
pple
pple
peche
per
bnn
cherry
cherry
bnn
'ornge'

[root@localhost ~]# cat fruit | tr -d 'apple'    //把所有含有这5个字母的都删除


ch
r
bnn
chrry
chrry
bnn
'orng'


[root@localhost ~]# cat fruit | tr -d '\n'    //删除换行符
appleapplepeachepearbananacherrycherrybanana'orange'[root@localhost ~]#   



[root@localhost ~]# cat fruit | tr -s 'p'    //对p字符去重,只保留第一个
aple
aple
peache
pear
banana
cherry
cherry
banana
'orange'

[root@localhost ~]# cat fruit | tr -s '\n'   //遇到多个回车只保留一个回车,相当于去除空行
apple
apple
peache
pear
banana
cherry
cherry
banana
'orange'

总结

1)基础正则表达式元字符的用法
2)扩展正则表达式元字符的用法
3)文本处理器的常用方法

sed、awk、sort、uniq、tr
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值