Linux Shell脚本编程一飞冲天版本

最近,在公司在弄svn钩子程序,验证开发提交的代码中是否error_log, print_r等环境调试打印字符,如果有这样的字符回滚事务,不允许提交,这个研究了下是通过一个钩子程序实现的,这个钩子程序的本质还是shell脚本,所以就快补shell脚本,顺便总结了一下,愿能给看到的人一点启示, 废话少说,直接学习!

一、什么是Shell脚本

1.1  实例入门

#!/bin/sh
cd ~
mkdir shell_tut
cd shell_tut
for ((i=0; i<10; i++)); do
    touch test_$i.txt
done

示例解释:

  • 第1行:指定脚本解释器,这里是用/bin/sh做解释器的

  • 第2行:切换到当前用户的home目录

  • 第3行:创建一个目录shell_tut

  • 第4行:切换到shell_tut目录

  • 第5行:循环条件,一共循环10次

  • 第6行:创建一个test_1…10.txt文件

  • 第7行:循环体结束

其中,cd, mkdir, touch 都是系统自带的程序,一般在/bin或者/usr/bin目录下。for, do, done 是sh脚本语言的关键字。

1.2 shell 脚本局限

shell只定义了一个非常简单的编程语言,所以,如果你的脚本程序复杂度较高,或者要操作的数据结构比较复杂,那么还是应该使用Python、Perl这样的脚本语言,或者是你本来就已经很擅长的高级语言。

sh和bash在这方面很弱,比如说:

  1. 它的函数只能返回字串,无法返回数组

  2. 它不支持面向对象,你无法实现一些优雅的设计模式

  3. 它是解释型的,一边解释一边执行,连PHP那种预编译都不是,如果你的脚本包含错误(例如调用了不存在的函数),只要没执行到这一行,就不会报错

1.3 shell脚本如何运行

chmod +x ./test.sh  #使脚本具有执行权限./test.sh  #执行脚本

   或者调用sh命令执行

/bin/sh test.sh

二、基础语法

2.1 变量定义与使用

变量名和等号之间不能有空格

your_name="qinjx 

使用一个定义过得变量,只要在变量名之前加上美元符号 $ 即可

#!/bin/bash
your_name="qinjx"
echo $your_name
echo ${your_name}

如何定义只读变量

#!/bin/bash
myUrl="http://www.w3cschool.cc"
readonly myUrl
myUrl="http://www.runoob.com"
输出结果:
bin/sh: NAME: This variable is read only.

使用 unset 命令可以删除变量。

unset variable_name

2.2 字符串常用操作

字符串可以用单引号,也可以用双引号,也可以不用引号。单双引号的区别跟PHP类似。

单引号

#!/bin/bash
str='this is a string'

单引号字符串的限制:

  • 单引号里的任何字符都会原样输出,单引号字符串中的变量是无效的。

  • 单引号字串中不能出现单引号(对单引号使用转义符后也不行)。

双引号

your_name='qinjx'
str="Hello, I know your are \"$your_name\"! \n"

双引号的优点:

  • 双引号里可以有变量。

  • 双引号里可以出现转义字符。

拼接字符串

your_name="qinjx"
greeting="hello, "$your_name" !"
greeting_1="hello, ${your_name} !"
echo $greeting $greeting_1

获取字符串长度

string="abcd"
echo ${#string} #输出 4

提取子字符串

以下实例从字符串第 2 个字符开始截取 4 个字符:

string="runoob is a great site"
echo ${string:1:4} # 输出 unoo

查找子字符串

查找字符 "i 或 s" 的位置:

string="runoob is a great company"
echo `expr index "$string" is`  # 输出 8

注意: 以上脚本中 "`" 是反引号,而不是单引号 "'",千万不要看错了。

2.3 数组操作

Bash Shell 只支持一维数组(不支持多维数组);

定义数组

在Shell中,用括号来表示数组,数组元素用"空格"符号分割开。

array_name=(value0 value1 value2 value3)

array_name[0]=value0

array_name[1]=value1

array_name[n]=valuen
读取数组

读取数组元素值的一般格式是:

#!/bin/bash

my_array=(A B "C" D)

echo "第一个元素为: ${my_array[0]}"

echo "第二个元素为: ${my_array[1]}"

echo "第三个元素为: ${my_array[2]}"

echo "第四个元素为: ${my_array[3]}"

使用 @ 或者 * 符号可以获取数组中的所有元素,例如:

#!/bin/bash
my_array[0]=A
my_array[1]=B
my_array[2]=C
my_array[3]=D
echo "数组的元素为: ${my_array[*]}"
echo "数组的元素为: ${my_array[@]}"

执行脚本,输出结果如下所示:

数组的元素为: A B C D
数组的元素为: A B C D

 

获取数组的长度

获取数组长度的方法与获取字符串长度的方法相同

#!/bin/bash


my_array[0]=A
my_array[1]=B
my_array[2]=C
my_array[3]=D


echo "数组元素个数为: ${#my_array[*]}"
echo "数组元素个数为: ${#my_array[@]}"

执行脚本,输出结果如下所示:
数组元素个数为: 4
数组元素个数为: 4

2.4 脚本传递参数

我们可以在执行 Shell 脚本时,向脚本传递参数,脚本内获取参数的格式为:$n。

n 代表一个数字,1 为执行脚本的第一个参数,2 为执行脚本的第二个参数,以此类推……

实例以下实例我们向脚本传递三个参数,并分别输出,其中 $0 为执行的文件名:

#!/bin/bash

echo "Shell 传递参数实例!";
echo "执行的文件名:$0";
echo "第一个参数为:$1";
echo "第二个参数为:$2";
echo "第三个参数为:$3";

为脚本设置可执行权限,并执行脚本,输出结果如下所示:

$ chmod +x test.sh

$ ./test.sh 1 2 3

Shell 传递参数实例!
执行的文件名:test.sh
第一个参数为:1
第二个参数为:2
第三个参数为:3

另外,还有几个特殊字符用来处理参数:

#!/bin/sh

echo "Shell 传递参数实例!";
echo "第一个参数为:$1";
echo "参数个数为:$#";
echo "传递的参数作为一个字符串显示:$*";
echo "脚本运行的当前进程ID号:$$";
echo "后台运行的最后一个进程的ID号:$!";
echo "传递的参数:$@";
echo "shell选项:$-";
echo "命令最后退出状态:$?";

#假设在脚本运行时写了三个参数 1、2、3,,则 " * " 等价于 "1 2 3"(传递了一个参数),而 "@" 等价于 "1" "2" "3"(传递了三个参数)。
echo "-- \$* 演示 ---"
for i in "$*"; do
echo $i
done
echo "-- \$@ 演示 ---"
for i in "$@"; do
echo $i
done

 

执行脚本,输出结果如下所示:

Shell 传递参数实例!
第一个参数为:1
参数个数为:3
传递的参数作为一个字符串显示:1 2 3
脚本运行的当前进程ID号:8264
后台运行的最后一个进程的ID号:
传递的参数:1 2 3
shell选项:hB
命令最后退出状态:0
-- $* 演示 ---
1 2 3
-- $@ 演示 ---
1
2
3

 

三、Bash基本语法

3.1 算术运算符 

Shell 和其他编程语言一样,支持多种运算符,包括:

  • 算数运算符

  • 关系运算符

  • 布尔运算符

  • 字符串运算符

  • 文件测试运算符

原生bash不支持简单的数学运算,但是可以通过其他命令来实现,例如 awk 和 expr,expr 最常用。

expr 是一款表达式计算工具,使用它能完成表达式的求值操作。

例如,两个数相加(特别注意:使用的是反引号 ` 而不是单引号 ')

#!/bin/bash

val=`expr 2 + 2`

echo "两数之和为 : $val"

执行脚本,输出结果如下所示:

两数之和为 : 4

两点注意:

  • 表达式和运算符之间要有空格,例如 2+2 是不对的,必须写成 2 + 2,这与我们熟悉的大多数编程语言不一样。

  • 完整的表达式要被 包含,注意这个字符不是常用的单引号,在 Esc 键下边。

算术运算符示例

#!/bin/bash

a=10

b=20

val=`expr $a + $b`

echo "a + b : $val"

val=`expr $a - $b`

echo "a - b : $val"

val=`expr $a \* $b`

echo "a * b : $val"

val=`expr $b / $a`

echo "b / a : $val"

val=`expr $b % $a`

echo "b % a : $val"

if [ $a == $b ]

then

  echo "a 等于 b"

fi

if [ $a != $b ]

then

  echo "a 不等于 b"

fi
执行脚本,输出结果如下所示:
a + b : 30

a - b : -10

a * b : 200

b / a : 2

b % a : 0

a 不等于 b

注意:

  • 乘号(*)前边必须加反斜杠()才能实现乘法运算。

  • if...then...fi 是条件语句,后续会有说明。

3.2 关系运算符

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

下面列出了常用的关系运算符,假定变量 a 为 10,变量 b 为 20:

运算符       说明                   举例

-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。

 

3.4 布尔运算符

下面列出了常用的布尔运算符,假定变量 a 为 10,变量 b 为 20:

运算符        说明                       举例

!    非运算,表达式为 true 则返回 false,否则返回 true。  [ ! false ] 返回 true。

-o    或运算,有一个表达式为 true 则返回 true。  [ $a -lt 20 -o $b -gt 100 ] 返回 true。

-a    与运算,两个表达式都为 true 才返回 true。  [ $a -lt 20 -a $b -gt 100 ] 返回 false。

 

3.5 逻辑运算符

以下介绍 Shell 的逻辑运算符,假定变量 a 为 10,变量 b 为 20:

运算符     说明                    举例

&&    逻辑的 AND           [[ $a -lt 100 && $b -gt 100 ]] 返回 false

||    逻辑的 OR            [[ $a -lt 100 || $b -gt 100 ]] 返回 true

 

3.6 字符串运算符

下面列出了常用的字符串运算符,假定变量 a 为 "abc",变量 b 为 "efg":

运算符     说明                     举例

=    检测两个字符串是否相等,相等返回 true。  [ $a = $b ] 返回 false。

!=    检测两个字符串是否相等,不相等返回 true。 [ $a != $b ] 返回 true。

-z    检测字符串长度是否为0,为0返回 true。  [ -z $a ] 返回 false。

-n    检测字符串长度是否为0,不为0返回 true。 [ -n $a ] 返回 true。

str    检测字符串是否为空,不为空返回 true。   [ $a ] 返回 true。

 

3.6 文件测试运算符

文件测试运算符用于检测 Unix 文件的各种属性。

属性检测描述如下:

操作符           说明                      举例

-b file    检测文件是否是块设备文件,如果是,则返回 true。  [ -b $file ] 返回 false。

-c file    检测文件是否是字符设备文件,如果是,则返回 true。 [ -c $file ] 返回 false。

-d file    检测文件是否是目录,如果是,则返回 true。 [ -d $file ] 返回 false。

-f file    检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回 true。    [ -f $file ] 返回 true。

-g file    检测文件是否设置了 SGID 位,如果是,则返回 true。  [ -g $file ] 返回 false。

-k file    检测文件是否设置了粘着位(Sticky Bit),如果是,则返回 true。  [ -k $file ] 返回 false。

-p file    检测文件是否是具名管道,如果是,则返回 true。   [ -p $file ] 返回 false。

-u file    检测文件是否设置了 SUID 位,如果是,则返回 true。  [ -u $file ] 返回 false。

-r file    检测文件是否可读,如果是,则返回 true。  [ -r $file ] 返回 true。

-w file    检测文件是否可写,如果是,则返回 true。  [ -w $file ] 返回 true。

-x file    检测文件是否可执行,如果是,则返回 true。 [ -x $file ] 返回 true。

-s file    检测文件是否为空(文件大小是否大于0),不为空返回 true。 [ -s $file ] 返回 true。

-e file    检测文件(包括目录)是否存在,如果是,则返回 true。    [ -e $file ] 返回 true。

 

3.7 echo命令

Shell 的 echo 指令与 PHP 的 echo 指令类似,都是用于字符串的输出。

 

read 命令从标准输入中读取一行,并把输入行的每个字段的值指定给 shell 变量:

#!/bin/sh

read name

echo "$name It is a test"

显示换行

echo -e "OK! \n"

显示不换行

echo -e "OK! \c"

显示结果定向至文件

echo "It is a test" > myfile

显示命令执行结果

 

echo `date`

3.8 printf 命令

printf 命令模仿 C 程序库(library)里的 printf() 程序。

标准所定义,因此使用printf的脚本比使用echo移植性好。

printf 使用引用文本或空格分隔的参数,外面可以在printf中使用格式化字符串,还可以制定字符串的宽度、左右对齐方式等。

默认printf不会像 echo 自动添加换行符,我们可以手动添加 \n。

printf 命令的语法:

printf  format-string  [arguments...]

参数说明:

  • format-string: 为格式控制字符串

  • arguments: 为参数列表。

#!/bin/bash

printf "%-10s %-8s %-4s\n" 姓名 性别 体重kg  

printf "%-10s %-8s %-4.2f\n" 郭靖 男 66.1234

printf "%-10s %-8s %-4.2f\n" 杨过 男 48.6543

printf "%-10s %-8s %-4.2f\n" 郭芙 女 47.9876

执行脚本,输出结果如下所示:


    姓名     性别   体重kg

    郭靖     男      66.12

    杨过     男      48.65

    郭芙     女      47.99

 

%s %c %d %f都是格式替代符。

%-10s 指一个宽度为10个字符(-表示左对齐,没有则表示右对齐),任何字符都会被显示在10个字符宽的字符内,如果不足则自动以空格填充,超过也会将内容全部显示出来。

%-4.2f 指格式化为小数,其中.2指保留2位小数。

 

 

3.9 test 命令

Shell中的 test 命令用于检查某个条件是否成立,它可以进行数值、字符和文件三个方面的测试。

 数值测试

参数     说明

-eq    等于则为真

-ne    不等于则为真

-gt    大于则为真

-ge    大于等于则为真

-lt    小于则为真

-le    小于等于则为真

实例

num1=100

num2=100

if test $[num1] -eq $[num2]

then

   echo '两个数相等!'

else

   echo '两个数不相等!'

fi

 

字符串测试

参数             说明

=              等于则为真

!=             不相等则为真

-z 字符串       字符串的长度为零则为真

-n 字符串       字符串的长度不为零则为真

实例

num1="runoob"

num2="runoob"

if test num1=num2

then

   echo '两个字符串相等!'

else

   echo '两个字符串不相等!'

fi

 

文件测试

 参数          说明

-e 文件名    如果文件存在则为真

-r 文件名    如果文件存在且可读则为真

-w 文件名    如果文件存在且可写则为真

-x 文件名    如果文件存在且可执行则为真

-s 文件名    如果文件存在且至少有一个字符则为真

-d 文件名    如果文件存在且为目录则为真

-f 文件名    如果文件存在且为普通文件则为真

-c 文件名    如果文件存在且为字符型特殊文件则为真

-b 文件名    如果文件存在且为块特殊文件则为真

 

 

另外,Shell还提供了与( -a )、或( -o )、非( ! )三个逻辑操作符用于将测试条件连接起来,其优先级为:"!"最高,"-a"次之,"-o"最低。

例如:

cd /bin

if test -e ./notFile -o -e ./bash

then

   echo '有一个文件存在!'

else

   echo '两个文件都不存在'

fi

 

四、函数与流程控制

和Java、PHP等语言不一样,sh的流程控制不可为空,如(以下为PHP流程控制写法)

4.1 if 语法

a=10

b=20

if [ $a == $b ]

then

  echo "a 等于 b"

elif [ $a -gt $b ]

then

  echo "a 大于 b"

elif [ $a -lt $b ]

then

  echo "a 小于 b"

else

  echo "没有符合的条件"

fi

 

4.2 for 循环

与其他编程语言类似,Shell支持for循环。

for循环一般格式为:

for var in item1 item2 ... itemN

do

   command1

   command2

   ...

   commandN

done

 

4.3 while 语句

while循环用于不断执行一系列命令,也用于从输入文件中读取数据,命令通常为测试条件。

#!/bin/sh

int=1

while(( $int<=5 ))

do

       echo $int

       let "int++"

done

 

脚本中使用了 let 命令,它用于执行一个或多个表达式,变量计算中不需要加上 $ 来表示变量。

while循环可用于读取键盘信息。

下面的例子中,输入信息被设置为变量FILM,按结束循环。

echo '按下 <CTRL-D> 退出'

echo -n '输入你最喜欢的电影名: '

while read FILM

do

   echo "是的!$FILM 是一部好电影"

done

4.4 无限循环

无限循环语法格式:

    while :

    do

       command

    done

或者


    while true

    do

       command

    done

或者

    for (( ; ; ))

 

4.5 until 循环

until循环执行一系列命令直至条件为真时停止。

until循环与while循环在处理方式上刚好相反。

一般while循环优于until循环,但在某些时候—也只是极少数情况下,until循环更加有用。

until 语法格式:

until condition

do

   command

done

条件可为任意测试条件,测试发生在循环末尾,因此循环至少执行一次—请注意这一点。

4.6 case语句

Shell case语句为多选择语句。

可以用case语句匹配一个值与一个模式,如果匹配成功,执行相匹配的命令。下面的脚本提示输入1到4,与每一种模式进行匹配:

echo '输入 1 到 4 之间的数字:'

echo '你输入的数字为:'

read aNum

case $aNum in

   1)  echo '你选择了 1'

   ;;

   2)  echo '你选择了 2'

   ;;

   3)  echo '你选择了 3'

   ;;

   4)  echo '你选择了 4'

   ;;

   *)  echo '你没有输入 1 到 4 之间的数字'

   ;;

esac

 

4.7 跳出循环

在循环过程中,有时候需要在未达到循环结束条件时强制跳出循环,Shell使用两个命令来实现该功能:break和continue。

break命令

break命令允许跳出所有循环(终止执行后面的所有循环)。

 

continue

continue命令与break命令类似,只有一点差别,它不会跳出所有循环,仅仅跳出当前循环。

 

4.8 函数

linux shell 可以用户定义函数,然后在shell脚本中可以随便调用。

下面的例子定义了一个函数并进行调用:

#!/bin/bash

demoFun(){

   echo "这是我的第一个 shell 函数!"

}

echo "-----函数开始执行-----"

demoFun

echo "-----函数执行完毕-----"

下面定义一个带有return语句的函数:

#!/bin/bash

funWithReturn(){

   echo "这个函数会对输入的两个数字进行相加运算..."

   echo "输入第一个数字: "

   read aNum

   echo "输入第二个数字: "

   read anotherNum

   echo "两个数字分别为 $aNum 和 $anotherNum !"

   return $(($aNum+$anotherNum))

}

funWithReturn

echo "输入的两个数字之和为 $? !"

函数返回值在调用该函数后通过 $? 来获得。

注意:

  • 所有函数在使用前必须定义。

  • 这意味着必须将函数放在脚本开始部分,直至shell解释器首次发现它时,才可以使用。

  • 调用函数仅使用其函数名即可。

函数参数

在Shell中,调用函数时可以向其传递参数。

在函数体内部,通过 $n 的形式来获取参数的值,例如,$1表示第一个参数,$2表示第二个参数...

 

注意,$10 不能获取第十个参数,获取第十个参数需要${10}。当n>=10时,需要使用${n}来获取参数。

另外,还有几个特殊字符用来处理参数:

参数处理     说明

$#    传递到脚本的参数个数

$*    以一个单字符串显示所有向脚本传递的参数

$$    脚本运行的当前进程ID号

$!    后台运行的最后一个进程的ID号

$@    与$*相同,但是使用时加引号,并在引号中返回每个参数。

$-    显示Shell使用的当前选项,与set命令功能相同。

$?    显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。

 

4.9 输入/输出重定向

大多数 UNIX 系统命令从你的终端接受输入并将所产生的输出发送回到您的终端。

一个命令通常从一个叫标准输入的地方读取输入,默认情况下,这恰好是你的终端。

同样,一个命令通常将其输出写入到标准输出,默认情况下,这也是你的终端。

重定向命令如下:

命令            说明

command > file    将输出重定向到 file。

command < file    将输入重定向到 file。

command >> file    将输出以追加的方式重定向到 file。

n > file    将文件描述符为 n 的文件重定向到 file。

n >> file    将文件描述符为 n 的文件以追加的方式重定向到 file。

n >& m    将输出文件 m 和 n 合并。

n <& m    将输入文件 m 和 n 合并。

<< tag    将开始标记 tag 和结束标记 tag 之间的内容作为输入。

需要注意的是文件描述符 0 通常是标准输入(STDIN),1 是标准输出(STDOUT),2 是标准错误输出(STDERR)。

输出重定向

重定向一般通过在命令间插入特定的符号来实现。特别的,这些符号的语法如下所示:

command1 > file1

上面这个命令执行command1然后将输出的内容存入file1。

注意:任何file1内的已经存在的内容将被新内容替代。如果要将新内容添加在文件末尾,请使用>>操作符。

 

输入重定向

和输出重定向一样,Unix 命令也可以从文件获取输入,语法为:

command1 < file1

这样,本来需要从键盘获取输入的命令会转移到文件读取内容。

注意:输出重定向是大于号(>),输入重定向是小于号(<)。

实例

接着以上实例,我们需要统计 users 文件的行数,执行以下命令:

 

$ wc -l users

2 users

也可以将输入重定向到 users 文件:

$  wc -l < users

2

注意:上面两个例子的结果不同:

  • 第一个例子,会输出文件名。

  • 第二个不会,因为它仅仅知道从标准输入读取内容。

command1 < infile > outfile

同时替换输入和输出,执行command1,从文件infile读取内容,然后将输出写入到outfile中。

重定向深入理解

一般情况下,每个 Unix/Linux 命令运行时都会打开三个文件:

  • 标准输入文件(stdin):stdin的文件描述符为0,Unix程序默认从stdin读取数据。

  • 标准输出文件(stdout):stdout 的文件描述符为1,Unix程序默认向stdout输出数据。

  • 标准错误文件(stderr):stderr的文件描述符为2,Unix程序会向stderr流中写入错误信息。

默认情况下,command > file 将 stdout 重定向到 file,command < file 将stdin 重定向到 file。

如果希望 stderr 重定向到 file,可以这样写:

$ command 2 > file

如果希望 stderr 追加到 file 文件末尾,可以这样写:

$ command 2 >> file

2 表示标准错误文件(stderr)。

如果希望将 stdout 和 stderr 合并后重定向到 file,可以这样写:

$ command > file 2>&1

或者

$ command >> file 2>&1

如果希望对 stdin 和 stdout 都重定向,可以这样写:

$ command < file1 >file2

command 命令将 stdin 重定向到 file1,将 stdout 重定向到 file2。

 

/dev/null 文件

如果希望执行某个命令,但又不希望在屏幕上显示输出结果,那么可以将输出重定向到 /dev/null:

$ command > /dev/null

/dev/null 是一个特殊的文件,写入到它的内容都会被丢弃。

如果尝试从该文件读取内容,那么什么也读不到。

但是 /dev/null 文件非常有用,将命令的输出重定向到它,会起到"禁止输出"的效果。

如果希望屏蔽 stdout 和 stderr,可以这样写:

$ command > /dev/null 2>&1

注意:0 是标准输入(STDIN),1 是标准输出(STDOUT),2 是标准错误输出(STDERR)。

4.10 文件包含

和其他语言一样,Shell 也可以包含外部脚本。

这样可以很方便的封装一些公用的代码作为一个独立的文件。

Shell 文件包含的语法格式如下:

. filename   # 注意点号(.)和文件名中间有一空格

source filename

 

 

——————————————————————————

参考:公众号SegmentFault:玩转 Linux - shell 编程基础

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值