shell脚本相关总结(1)

一、shell简介

shell是一个命令解释器,提供用户和机器之间的交互。它支持特定的语法,比如逻辑判断、循环。每个用户都可以有自己特定的shell,并且还有其他的shell,如zsh、ksh等。Centos 7默认的shell为bash(Bourne Agin Shell)
CentOS系统中支持很多shell,可以通过查看/etc/shells文件,查看所支持的shell,目前大多数的Linux基本都使用bash。

[root@localhost ~]# cat /etc/shells
/bin/sh
/bin/bash
/usr/bin/sh
/usr/bin/bash
/bin/tcsh
/bin/csh

Shell是一个用C语言编写的程序,它是用户使用Linux的桥梁。Shell既是一种命令语言,又是一种程序设计语言。
Shell也是一种应用程序,这个应用程序提供了一个界面,用户通过这个界面访问操作系统内核的服务。
1.编译型语言
(1)优点:编译器一般会有预编译的过程,对代码进行优化。因为编译只做一次,运行时不需要编译,所以编译型语言的程序执行效率高,可以脱离语言环境独立运行。

(2)缺点:编译之后如果需要修改就需要整个模块重新编译。编译的时候根据对应的运行环境生成机器码,不同的操作系统之间移植就会有问题,需要根据运行的操作系统环境编译不同的可执行文件。
代表语言:C、C++、Pascal、Object-C、swift等。
2.解释型语言
(1)优点:有良好的平台兼容性,在任何环境中都可以运行,前提是安装了解释器(虚拟机)。相对来说比较灵活,比如修改代码的时候可以直接修改,并且可以快速部署,不用停机维护。

(2)缺点:每次运行的时候都要解释一遍,效率较低,性能上不如编译型语言。
代表语言:JavaScript、Python、Erlang、PHP、Perl、Ruby

bash shell有两种工作模式:互动模式和脚本模式。脚本模式效率更高,可以实现自动化。
编写脚本如下:

[root@localhost ~]# vim helloworld.sh
#!/bin/bash
#this line is a comment
echo "hello world"

3.运行脚本的方法
(1)可以用bash去运行

[root@localhost ~]# bash helloworld.sh
hello world

(2)“.”也都可以执行脚本,且不需要可执行权限

[root@localhost ~]# . helloworld.sh
hello world

(3)给脚本添加可执行权限,然后直接就可以执行

[root@localhost ~]# chmod +x helloworld.sh
[root@localhost ~]# ./helloworld.sh
hello world

注意:脚本是各种命令的集合,最终都是要执行服务。
4.查看各种命令存储的位置

[root@localhost ~]# echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin

二、变量

变量表示其值是可以变化的量。从变量的本质来说,变量名是指向一片用于存储数据的内存空间。而且变量有局部变量、环境变量之分。在脚本中,往往需要使用变量来存储有用信息,比如文件名、路径名、数值等。通过这些变量可以控制脚本的运行过程。
1.变量的分类

(1)局部变量
指在某个shell中生效的变量,对其他shell来说无效。
局部变量的作用域被限定在声明它们的shell中,可以使用local内的命令来“显示”的声明局部变量,但仅限于函数内使用。

(2)环境变量
通常又称“全局变量”,在shell脚本中,变量默认就是全局的。
为了让子shell继承当前shell的变量,可以使用export命令将其定义为环境变量。

2.环境变量的设置
(1)declare -x

[root@localhost ~]# declare -x class="linux base"
[root@localhost ~]# echo $class
linux base

(2)export

[root@localhost ~]# export class1="linux"
[root@localhost ~]# echo $class1
linux

(3)变量名=变量值

[root@localhost ~]# class2="nihao"
[root@localhost ~]# echo $class2
nihao

总结

declare -x和export这种设置变量的方式,是全局的环境变量。
特点:子进程会继承父进程的环境变量。

"变量名=变量值"的方式,默认只在当前进程有效。
如果想要子进程也有效,可以使用前两种暴露的方式,或者将变量添加到/etc/profile文件中。

注意:等号左右不能加空格,引号可以是单引号,也可以是双引号,也可以是引用一条命令执行后的结果(使用反引号)。

[root@localhost ~]# name=`cat /etc/fstab`
[root@localhost ~]# echo $name
# # /etc/fstab # Created by anaconda on Fri Nov 27 12:21:18 2020 # # Accessible filesystems, by reference, are maintained under '/dev/disk' # See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info # /dev/mapper/centos-root / xfs defaults 0 0 UUID=7f7a3c9c-ae04-466c-868f-2db1542c7438 /boot xfs defaults 0 0 /dev/mapper/centos-swap swap swap defaults 0 0

使用反引号之后,显示格式变化,如果想要按照原格式显示,可以加上双引号。

[root@localhost ~]# echo "$name"

#
# /etc/fstab
# Created by anaconda on Fri Nov 27 12:21:18 2020
#
# Accessible filesystems, by reference, are maintained under '/dev/disk'
# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info
#
/dev/mapper/centos-root /                       xfs     defaults        0 0
UUID=7f7a3c9c-ae04-466c-868f-2db1542c7438 /boot                   xfs     defaults        0 0
/dev/mapper/centos-swap swap                    swap    defaults        0 0

其实变量的值也可以是一个变量。

[root@localhost ~]# x1="a"
[root@localhost ~]# x2="b"
[root@localhost ~]# x3="$x1"
[root@localhost ~]# echo "$x1"
a
[root@localhost ~]# echo "$x3"
a
[root@localhost ~]# x1="c"
[root@localhost ~]# echo "$x1"
c
[root@localhost ~]# echo "$x3"
a

可以看出改变x1的值,x3的值不会跟着改变。这是因为当我们设置变量时,x3又重新指定了一块"存储空间",和x1的值已经没有关系了。
3.变量命名法则
shell中的变量必须以字母或者下划线开头,后面可以跟数字、字母和下划线,长度没有限制,区分大小写。比如:(单驼峰、双驼峰、三驼峰)
4.变量赋值和取值
定义变量:变量名=变量值
(1)注意变量名和变量值之间用等号紧紧相连,之间没有任何空格。

[root@localhost ~]# name=nihao
[root@localhost ~]# name= nihao
-bash: nihao: 未找到命令

(2)注意当变量值中有空格时必须用引号括起,否则会出现错误,可以是双引号,也可以是单引号。

[root@localhost ~]# name=li lei
-bash: lei: 未找到命令
[root@localhost ~]# name="li lei"

(3)变量的取值,在变量名前加$。

[root@localhost ~]# echo $name
li lei

注意:在多数情况下,运行脚本如果提示错误,仔细检查脚本后还是不确定哪里出现问题,那么这时不妨将变量的取值写成标准格式,可能就会解决问题。
5.取消变量
使用unset+变量名。
函数也可以被取消,unset后面也可以跟上函数名来取消函数。

[root@localhost ~]# unset name
[root@localhost ~]# echo ${name}

注意:在不用变量时,会取消变量,虽然退出进程也可以取消变量,但一般都会人为的去取消。
set命令可以显示所有变量:包括局部变量和环境变量。也会显示一些函数。
env、printenv、export、declare -x也可以。
6.特殊变量
局部变量只在当前shell有效,环境变量的有效范围为当前shell和子shell。除了这些还有其他一些变量也需要注意。
(1)只读变量(常量)
只能声明,但不能修改和删除。

[root@localhost ~]# readonly name1="wukong"
[root@localhost ~]# echo $name1
wukong
[root@localhost ~]# name1="bajie"
-bash: name1: 只读变量

还可以使用declare -r声明常量。

[root@localhost ~]# declare -r name2="bajie"
[root@localhost ~]# echo $name2
bajie
[root@localhost ~]# name2="baima"
-bash: name2: 只读变量

查看常量值:readonly:有效期直到进程结束。

[root@localhost ~]# readonly -p
declare -r BASHOPTS="checkwinsize:cmdhist:expand_aliases:extglob:extquote:force_fignore:histappend:interactive_comments:login_shell:progcomp:promptvars:sourcepath"
declare -ir BASHPID
declare -r BASH_COMPLETION_COMPAT_DIR="/etc/bash_completion.d"
declare -ar BASH_REMATCH='()'
declare -ar BASH_VERSINFO='([0]="4" [1]="2" [2]="46" [3]="2" [4]="release" [5]="x86_64-redhat-linux-gnu")'
declare -ir EUID="0"
declare -ir PPID="1486"
declare -r SHELLOPTS="braceexpand:emacs:hashall:histexpand:history:interactive-comments:monitor"
declare -ir UID="0"

7.括号的使用
(1)小括号用法:一次性使用,不会对环境产生影响。

[root@localhost ~]# (x=zj;echo $x;)
zj
[root@localhost ~]# echo $x

(2)大括号用法:前后有空格,这个对全局有影响。

[root@localhost ~]# { x=zj;echo $x; }
zj
[root@localhost ~]# echo $x
zj

8.位置变量
shell中还有一些预先定义的特殊只读变量,它们的值只有在脚本运行时才能确定。

变量意义
$0代表脚本本身名字。
$1----$9第一个位置参数----第九个位置参数。
$#脚本参数的个数总和。
$@表示脚本的所有参数。
$*表示脚本的所有参数。
[root@localhost ~]# vim t1.sh
#!/bin/bash
echo "这个脚本的名字是:$0"
echo "参数一共有:$#个"
echo "参数的列表是:$@"
echo "参数的列表是:$*"
echo "第一个参数是:$1"
echo "第二个参数是:$2"
echo "第三个参数是:$3"
echo "第十二个参数是:${12}"

如果想让它识别为12,就要用到花括号。

[root@localhost ~]# bash t1.sh {1..13}
这个脚本的名字是:t1.sh
参数一共有:13个
参数的列表是:1 2 3 4 5 6 7 8 9 10 11 12 13
参数的列表是:1 2 3 4 5 6 7 8 9 10 11 12 13
第一个参数是:1
第二个参数是:2
第三个参数是:3
第十二个参数是:12

假设要复制一个文件到另一台虚拟机。
使用scp命令。

[root@localhost ~]# cat /etc/redhat-release > myrelease.txt
[root@localhost ~]# cat myrelease.txt
CentOS Linux release 7.7.1908 (Core)
[root@localhost ~]# vim scp.sh
#!/bin/bash
echo "start copy..."
scp $* root@192.168.229.209:/root
echo "copy is finished"
[root@localhost ~]# bash scp.sh myrelease.txt
start copy...
myrelease.txt                   100%   37      26.5KB/s      00:00
copy is finished

当然也可以做到免密登录,传输文件时就不要输入密码。

[root@localhost ~]# ssh-keygen -t rsa
[root@localhost ~]# ssh-copy-id root@192.168.229.209
[root@localhost ~]# bash scp.sh myrelease.txt
start copy...
myrelease.txt                   100%   37      28.5KB/s      00:00
copy is finished

注意
在两者有双引号的前提下,显示效果才会区分,如果没有双引号,显示效果一样。

$*:代表脚本的所有参数,把显示的结果当做一个整体显示。

$@:代表脚本的所有参数,把收集到的结果分开来显示。

9.$0引用名称的使用
如果把一个脚本添加一个软链接。这时再运行脚本,那么它的名称应该是显示原来的名字还是修改后的名字呢?

[root@localhost ~]# ln -s t1.sh link.sh
[root@localhost ~]# bash link.sh
这个脚本的名字是:link.sh
参数一共有:0个
...

可以利用这一点,即便是同一个脚本,也可以拓展出不同的功能。
10.shift命令
整体左移

[root@localhost ~]# vim t1.sh
#!/bin/bash
echo "这个脚本的名字是:$0"
echo "参数一共有:$#个"
echo "参数的列表是:$@"
echo "参数的列表是:$*"
echo "第一个参数是:$1"
echo "第二个参数是:$2"
echo "第三个参数是:$3"
echo "第十二个参数是:${12}"
shift
echo "这个脚本的名字是:$0"
echo "参数一共有:$#个"
echo "参数的列表是:$@"
echo "参数的列表是:$*"
echo "第一个参数是:$1"
echo "第二个参数是:$2"
echo "第三个参数是:$3"
echo "第十二个参数是:${12}"
shift
echo "这个脚本的名字是:$0"
echo "参数一共有:$#个"
echo "参数的列表是:$@"
echo "参数的列表是:$*"
echo "第一个参数是:$1"
echo "第二个参数是:$2"
echo "第三个参数是:$3"
echo "第十二个参数是:${12}"
[root@localhost ~]# bash t1.sh {1..13}
这个脚本的名字是:t1.sh
参数一共有:13个
参数的列表是:1 2 3 4 5 6 7 8 9 10 11 12 13
参数的列表是:1 2 3 4 5 6 7 8 9 10 11 12 13
第一个参数是:1
第二个参数是:2
第三个参数是:3
第十二个参数是:12
这个脚本的名字是:t1.sh
参数一共有:12个
参数的列表是:2 3 4 5 6 7 8 9 10 11 12 13
参数的列表是:2 3 4 5 6 7 8 9 10 11 12 13
第一个参数是:2
第二个参数是:3
第三个参数是:4
第十二个参数是:13
这个脚本的名字是:t1.sh
参数一共有:11个
参数的列表是:3 4 5 6 7 8 9 10 11 12 13
参数的列表是:3 4 5 6 7 8 9 10 11 12 13
第一个参数是:3
第二个参数是:4
第三个参数是:5
第十二个参数是:

注意:默认移动一位,当然也可以设置移动多少位,在shift后面直接加上想要移动的位数即可。
11.退出状态
进程使用退出状态来报告成功或者失败。
可以用如下命令去验证:

[root@localhost ~]# ls
t1.sh
[root@localhost ~]# echo $?
0
[root@localhost ~]# ls /abc
ls: 无法访问/abc: 没有那个文件或目录
[root@localhost ~]# ehco $?
2

0代表成功,1~255代表失败。
当然退出返回码是可以修改的。

[root@localhost ~]# vim t2.sh
#!/bin/bash
echo "t2脚本所有参数是:$*"
bash t3.sh "$@"
exit 10
[root@localhost ~]# bash t2.sh
t2脚本所有参数是:
t3脚本的第一个参数:
[root@localhost ~]# echo $?
10

我们根据不同的返回码,就可以判断出系统的运行状态。假设,我们规定了计算机会有几种情况,如果说一种情况返回10,另一种情况返回20,还有30,那么就可以根据系统返回的值的不同来判断出系统肯定是满足了某种条件。这样就可以作为定位判断系统状态的依据,其实在上网时有时会返回404,其实也是类似这种方法。

状态码意义
200OK
404Not Found
3xx重定向
4xx客户端错误
5xx服务器错误

当然exit命令在外部也可以使用,意思是退出bash。

三、数组

数组是一种特殊的数据结构,其中的每一项被称为一个元素,每个元素都可以用索引的方式取出对应的值。使用数组的典型场景是一次性要记录很多类型相同的数据(但不一定必须要相同)。
比如记录班级中所有人的数学成绩,如果不用数组来处理,那就只能定义所有人成绩的变量。shell中的数组对元素个数没有限制,但只支持一维数组。
1.定义数组
(1)使用declare -a命令定义数组

[root@localhost ~]# declare -a list
[root@localhost ~]# list[0]=tom
[root@localhost ~]# list[1]=jerry
[root@localhost ~]# list[2]=dog
[root@localhost ~]# echo ${list[0]}
tom
[root@localhost ~]# echo ${list[1]}
jerry
[root@localhost ~]# echo ${list[2]}
dog

(2)在创建属组时赋值

[root@localhost ~]# name=("zhangsan" "lisi" "wangwu")
[root@localhost ~]# echo ${name[0]}
zhangsan
[root@localhost ~]# echo ${name[1]}
lisi
[root@localhost ~]# echo ${name[2]}
wangwu

用负数表示倒叙

[root@localhost ~]# echo ${name[-3]}
zhangsan
[root@localhost ~]# echo ${name[-2]}
lisi
[root@localhost ~]# echo ${name[-1]}
wangwu

注意: 注意数组多个元素之间不要用逗号隔开,否则会把多个元素当做整体一起输出。
(3)使用跳号赋值,也就是可以指定索引号。

[root@localhost ~]# score=([1]=1 [3]=3 [5]=5)
[root@localhost ~]# echo ${score[1]}
1
[root@localhost ~]# echo ${score[3]}
3
[root@localhost ~]# echo ${score[5]}
5

2.数组的取值
默认显示数组第一个元素值

[root@localhost ~]# echo ${name=[0]}
zhangsan
[root@localhost ~]# echo ${name}
zhangsan

取出对应索引下标的值

[root@localhost ~]# echo ${name[2]}
wangwu
[root@localhost ~]# echo ${name[1]}
lisi
[root@localhost ~]# echo $[name[0]}
zhangsan

注意:注意数组内索引为0的才是第一个。
3.一次取出数组所有的值
@得到的是以空格隔开的元素

[root@localhost ~]# echo ${name[@]}
zhangsan lisi wangwu

*得到的是一整个字符串

[root@localhost ~]# echo ${name[*]}
zhangsan lisi wangwu

4.数组的长度:数组元素的个数
使用“#”来获取数组元素的个数。

[root@localhost ~]# echo ${#name[@]}
3
[root@localhost ~]# echo ${#name[*]}
3

5.数组的截取(分片)
可以截取某个元素的一部分,对象可以是整个数组或某个元素。
定义数组

[root@localhost ~]# number=(1 2 3 4 5 6 7 8)
[root@localhost ~]# echo ${number[*]}
1 2 3 4 5 6 7 8
[root@localhost ~]# echo ${#number[*]}
8

取出第一个到第3个元素的值

[root@localhost ~]# echo ${number[@]:0:3}
1 2 3

取出第3个到第6个元素的值

[root@localhost ~]# echo ${number[@]:2:4}
3 4 5 6

取某个元素的第几个字符到第几个字符。

[root@localhost ~]# word=(hello world and welcome)
[root@localhost ~]# echo ${word[2]:0:3}
and
[root@localhost ~]# echo ${word[1]:0:3}
wor
[root@localhost ~]# echo ${word[1]:0:4}
worl

总结:左边的数字表示的是下标(从第几个开始截取),右边表示的是截取的个数。
6.连接数组
将若干个数组进行拼接操作,将两个数组的元素全部连接。

[root@localhost ~]# new=(${number[@]} ${word[@]})
[root@localhost ~]# echo ${new[@]}
1 2 3 4 5 6 7 8 hello world and welcome

7.替换元素
将数组内某个元素的值替换成其他值。

[root@localhost ~]# name=(zhangsan lisi wangwu zhaoliu)
[root@localhost ~]# echo ${name[@]}
zhangsan lisi wangwu zhaoliu

将lisi替换为lilei

[root@localhost ~]# name=(${name[@]/lisi/lilei})
[root@localhost ~]# echo ${name[@]}
zhangsan lilei wangwu zhaoliu

取消数组或元素可以使用unset命令
取消数组中的一个元素

[root@localhost ~]# unset name[2]
[root@localhost ~]# echo ${name[@]}
zhangsan lilei zhaoliu

取消整个数组就相当于取消全部变量

[root@localhost ~]# unset name
[root@localhost ~]# echo ${name[@]}

8.转义和引用

(1)转义:shell中有很多特殊字符有特殊意义,但是有时会造成误解,需要转义才可以使用,转义符号为“\”。

(2)引用:指将字符串用某种符号括起来,以防止特殊字符被解析为其他意思。
shell中一共有4种引用符,分别为双引号、单引号、反引号和转义符。
双引号可以引用除$符号、反引号、转义符之外的所有字符。
单引号可以引用所有字符。
反引号则会将反引号中的内容解释为系统命令。
四、运算符

shell中的运算符主要有比较运算符(用于整数比较)、字符串运算符(用于字符串测试)、文件操作运算符(用于文件测试)、逻辑运算符、算术运算符、位运算符、自增自减运算符等。
1.算术运算符
指加、减、乘、除、余、幂等常见的算术运算,以及加等、减等、乘等、除等、余等复合算术运算。
注意:shell只支持整数计算,也就是说所有可能产生小数的运算都会舍去小数部分。

运算符运算符举例运算结果
+(加运算符)1+12
-(减运算符)2-11
*(乘运算符)2*36
/(除运算符)9/42
%(余运算符)10%31
**(幂运算符)2**38
+=(加等运算符)x=8;x+=210
-=(减等运算符)x=8;x-=26
*=(乘等运算符)x=8;x*=216
/=(除等运算符)x=8;x/=24
%=(余等运算符)x=8;x%=20

2.shell算术运算的四种方式
(1)使用expr外部程式

[root@localhost ~]# a=`expr 4 + 5`
[root@localhost ~]# echo $a
9

注意:‘4’ ‘+’ '5’这三者之间要有空格。
(2)使用 $(( ))

[root@localhost ~]# a=$((4 + 5))
[root@localhost ~]# echo $a
9

(3)使用 $[ ]

[root@localhost ~]# a=$[4 + 5]
[root@localhost ~]# echo $a
9

(4)使用let命令

[root@localhost ~]# let a=4+5
[root@localhost ~]# echo $a
9

(5)总结

加法减法乘法除法取模幂运算
expr命令expr 2 + 3expr 2 - 3expr 2 * 3expr 2 / 3expr 2 % 3no
$(())$((2+3))$((2-3))$((2*3))$((2/3))$((2%3))$((2**3))
$[]$[2+3]$[2-3]$[2*3]$[2/3]$[2%3]$[2**3]
letlet a=m+nlet a=m-nlet a=m*nlet a=m/nlet a=m%nlet a=m**n

注意:let命令可以直接用变量名,并且支持变量名和具体数值之间的各种运算。
3.与运算、或运算、异或运算
先了解10进制转2进制。
将一个十进制数除以二,得到的商再除以二,依此类推直到商等于一或零时为止,倒取除得的余数,即换算为二进制数的结果。
只需记住要点:除二取余,倒序排列。
在这里插入图片描述
二进制转十进制的转换原理:从二进制的右边第一个数开始,每个乘以2的n次方,n从0开始,每次递增1。然后得出来的数相加即是十进制数。
在这里插入图片描述
(1)与运算:&(并且)and

符号意义
0false
1true
0&00
0&10
1&00
1&11

总结:有假必为假,同真才为真。
(2)或运算:|(或者)or

0|0=0
0|1=1
1|0=1
1|1=1

总结:有真必为真,同假才为假。
(3)异或运算:^异或

符号意义
0^11
0^00
1^01
1^10

总结:同性为假,异性为真。
(4)短路与&&逻辑与

符号意义
0&&00
0&&10
1&&00
1&&11

如果是命令:cmd1 && cmd2
总结:如果cmd1为假,cmd2不需要执行。反之cmd1为真,需要执行cmd2。
(5)短路或 || 逻辑或

0||0=0
0||1=1
1||0=1
1||1=1
cmd1 || cmd2

总结:如果cmd1为真,cmd2不需要执行。反之cmd1为假,需要执行cmd2。

五、关系运算符

关系运算符只支持数字,不支持字符串,除非字符串的值是数字。

符号意义例子
-eq检测两个数是否相等,相等返回true。[ $a -eq $b ]返回false。
-ne检测两个数是否不相等,不相等返回true。[ $a -ne $b ]返回true。
-gt检测左边的数是否大于右边的,如果是,则返回true。[ $a -gt $b ]返回false。
-lt检测左边的数是否小于右边的,如果是,则返回true。[ $a -lt $b ]返回true。
-ge检测左边的数是否大于等于右边的,如果是,则返回true。[ $a -ge $b ]返回false。
-le检测左边的数是否小于等于右边的,如果是,则返回true。[ $a -le $b ]返回true。

1.例子
如果参数1大于参数2,那么两数相减,并输出结果值“因为参数1大于参数2,所以两数相减,结果值为:”
如果参数1等于参数2,那么两数想乘,并输出结果值“因为参数1等于参数2,所以两数相乘,结果值为:”
如果参数1小于参数2,那么两数想加,并输出结果值“因为参数1小于参数2,所以两数相加,结果值为:”

[root@localhost ~]# vim bijiao.sh
#!/bin/bash 
if [ $1 -gt $2 ] 
then 
         echo "参数$1 大于 $2 ,所以两数相减等于:`expr $1 - $2`" 
fi
if [ $1 -eq $2 ] 
then 
         echo "参数$1 等于 $2,所以两数相乘等于:`expr $1 \* $2`" 
fi
if [ $1 -lt $2 ] 
then 
         echo "参数$1 小于 $2 ,所以两数相加等于:`expr $1 + $2`" 
fi
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值