shell 编程 学习笔记

一、 变量

1, 用的时候可以写为$var或者${var},但当变量后有字母或者其他字符时必须用后者。

2, 用printf打印时变量最好用””,如printf  “%s\n” “$var”

3, 取消变量,var= 或者unset var(先尝试取消变量否则就取消函数,-f代表函数,-v代表变量,unset –f  fn)

4, 在双引号中,可以替换变量、替换命令执行结果、替换算术运算结果。若在双引号中用\可抑制变量的替换。

5, 变量的作用范围:仅限于当前的shell,但环境变量可以在任何shell环境中有效。在执行sh文件时会另开一个shell环境,从当前环境中继承环境变量。要想在当前shell中运行必须用. cd.sh或者sourec cd.sh

6, 环境变量:要把一个变量变成环境变量要用export,如export var =”hello”或者export var.

执行export或者export  -p会列出目前的环境变量。declare –x var一样可以设为环境变量。

7, BASH内置的环境变量:

BASHbash完整的变量名,如/bin/bash 或者 /usr/local/bin/bash

BASH_EVN:执行shell script时若此变量不为空则首先执行它。

BASH_VERSIONbash的版本

CAPATHcd命令搜索的路径(类似在环境变量中搜索命令)

EVN:以互动模式调用sh或者在POSIX模式下时,首先检查此变量,有则首先执行它

EUID:有效的uid

FCEDITOR:fc命令默认使用的比较器

FIGNORE:在进行文件名自动 补齐时,忽略的扩展名列表。用:隔开,如”.o:~:.txt”

FUNCNAME:函数执行时的函数名(类似于php中的魔术变量__FUNCTION__

GLOBIGNORE:做样式比较时忽略的文件名列表,用:隔开

GROUPS:数组变量,包含用户所属的组群列表

HISTCMD:当前指令执行完后它在历史指令中的排列编号,

HISTCONTROL:控制指令是否存入历史脚本文件中

          ignorespace:排除开头有空格的指令

          ignoredups:连续重复的指令只存一个

          ignoreboth:结合前两者的功能

HISTFILE:设定历史脚本文件的路径文件名,通常是~/.bash_history

HISTFILESIZE:历史脚本文件存储指令的最大行数,默认500

HISTIGNORE:不存入历史的指令,以:隔开,如ls:ps:cd:t*:\&(&代表最后一个历史指令,若一直健入重复的指令只存入一个,&又是后台执行符号,需要用\转义)

HISTSIZE:在互动模式中shell记住的历史指令数目,默认500

HOME:当前用户的家目录

HOSTFILE:包含自动补齐主机名的数据文件,须和/etc/hosts格式相同

HOSTNAME:主机名称

HOSTTYPE:主机形态,如i386

IFS:定义字段分隔符,默认为:空格、tag字符、换行字符。

IGNOREEOF:在按Ctrl+D时,出现几次EOF才能注销系统。

INPUTRC:设定命令行函数库readline的启动配置文件,可覆盖~/.inputrc

LANG:目前语系的名称

LC_ALL:目前的locale,可覆盖LANDLC_*的设定

LC_COLLATElocale字母排序

LC_CTYPElocale字符分类

LC_MESSAGESlocale信息显示的转换,如

LINENOscript脚本已执行到的行数

MACHTYPE:描述主机型态的GUN格式,如i386-pc-linux-gun

MAIL:邮件文件的名称

MAILCHECK:每隔多久检查一下邮件,默认是60

MAILPATH:设定检查新邮件的文件名,多个用:隔开

OLDPATH:前一个工作目录(有点类似于cd  -

OPTARG:使用getopts处理选项时,取得的选项的参数

OPTERR:若此值为1,当getopts发生错误时,不管选项行第一个字符是否为:,都显示错误信息

OSTYPE:操作系统,如linux-gun

PATH:命令搜索的路径,多个用:隔开

PPID:父进程编号

PROMPT_COMMAND:出现在主要提示符$PS1之前执行的命令

PS1:默认为\s-\v\$   <主要提示符代码见背部>

PS2:次提示符号,默认为>

PS3select选单的提示符,默认为#?

PS4:追踪程序时各行的提示符样式,默认为+

PWD:当前的工作目录

RANDOM:产生随机数(需要随机种子)

REPLY:在selectread没有设定读取的变量时,默认的变量名称

SECONDS:目前的shell script已执行的时间(以秒为单位)

SHELLshell的文件路径,默认为”/bin/bash”

SHELLOPTS:经set –o指令开启的shell选项,以:分隔

SHLVL:子shell的层级数

TIMEFORMAT:设定time统计运行时间的格式《更详细的见背后》

TMOUTshell脚本执行的超时时限

UID:用户ID

$1~$n:位置参数,传入脚本或者函数的参数,第一个参数是$1,第二个是$2,依次类推,第10个是${10}$0表示执行程序的名称

$*:代表所有位置的参数,为一字符串,如”ABC  123  XYZ”

$@:所有位置的参数组成的串行,如”ABC”、”123”、”XYZ”

$#:位置参数的个数

$?:上一个命令执行结束后的传回值,0代表执行成功,非0代表失败

$$:目前shell  script的进程编号

$!:上一个后台程序的进程编号

$_1script执行时为bash的绝对路径,如/bin/bash2,上一个命令执行时最后一个位置参数。3,检查邮件时,为邮件文件名。

8, 设变量为只读变量

readonly var设定var变量为只读,执行readonly或者readonly –p列出所有的只读变量。

readonly –f 函数名:设定函数只读,不可修改。

readonly –a 数组名:设定数组只读,不可修改。

或者declare –r var设定var只读

9, declare 用法:

选项

说明

-p

显示变量属性  Declare –p var    显示var的属性

-a

变量是一个数组    Declare –a array     设定array为一个数组

-f

搜寻命令时只找函数   Declare –f fn   寻找fn时只在函数列表里找,不搜寻其他别名或者外部命令

-i

变量是一个整数  Declare –I var   设定var为一整数

-F

显示所有的函数名称及其属性     Declare -F

-r

设定变量只读    Declare –r var      Var变量只读

-t

设定变量具有trace属性,有利于排除。declare –t xyz=111

-x

设为环境变量,declare –x mypath

10, 自定义环境

大多数主机在开设帐号后会自动在主目录下建立.bash_profile.bashrc这两个文件,至于.bash_logout一般默认没有,需要自己建立。一般在.bash_profile中设定全局适用的命令、搜寻路径和环境变量,而其他大部分设定在.bashrc里,所以.bash_profile比较小,而.bashrc比较大。

文件名

执行时机

~/.bash_profile

登录时

~/.bashrc

执行shell  script

~/.bash_logout

注销时

而系统管理员还要维护另外三个配置文件:

/etc/profile

/etc/bash.bashrc

/etc/skel目录下所有的文件

其中/etc/profile/etc/bash.bashrc的设定会影响所有的账号使用。在/etc/profile中设定的有umaskPATH、多国语言环境、提示符号、别名等。/etc/bash.bashrc的内容大外如下:[ -f  /etc/profile ] && . /etc/profile 表示当执行交互式的shell时会检查/etc/profile是否存在,若存在就执行。

/etc/skel的作用是:当管理员开设新账号时,这个目录下的所有的文件会拷一份到新账号home目录下,作为用户的环境文件。其中包括 .bash_profile.bashrc文件。

11,数组:第一个元素由0开始,并且如1+2这样的算术表达式也可以作为索引,${arr[5]}.

建立数组时可以指定个别元素的索引,如arr=([3]=77  [5]=100  55)4个元素为77,第6个元素为1007全元素为55.

$(arr[@])一次取出数组的全部元素,得到以空白隔开的全部元素,如77  100  55

$(arr[*])一次取出数组的全部元素,得到一个字符串,如”77  100  55”

$(#arr[@])或者 $(#arr[*])取得数组元素的个数

unset arr取消数组

unset arr[4]取消数组的一个元素

11, Here Documentcat<<’wendao’关闭变量替换功能。cat<<-‘wendao’去掉每行之前的tab字符。:<<wendao批注,什么都不做。

二、 变量扩展${var}、命令替换$(command)及算术扩展$((算术式))

1, 变量存在:变量有值或者其值为空(null),若用unset掉变量,则变量不存在。

${变量-默认值}:若变量存在返回变量值,否则就返回默认值。

${变量:-默认值}:若变量不存在或者为空就传回默认值,否则返回变量值。

${变量:=默认值}:若变量不存在或者为空就给变量设一个默认值,否则就返回变量的值。

${变量:?提示信息}:若变量不存在或者其值为空提示错误信息,并停止执行。

${变量:+真值}:变量存在且其值非空则返回真值,否则返回空值。

:表明同时测试空值,若去掉:表示只测存在性,不测空值。

2, 变量扩展:字符串第一个字符编号为0,依次累加。

${变量:位置起点:长度}:从位置起点开始截取字符串,若没有长度则取以后的全部字符。${@:起点:个数}:截取位置参数,若无个数则取以后所有的参数。

${#变量名称}:返回变量值的字符串长度。

${#数组[@]}:取数组元素个数

${#数组[*]}:取数组元素个数

expr length “字符串”:获取字符串长度

expr “字符串”:”.*”:利用字符串匹配来计算字符串的长度

${变量#样式}:从变量的左边开始比较样式,删除最短符合样式的字符串

${变量##样式}:从变量的左边开始比较样式,删除最长符合样式的字符串

${变量%样式}:从变量的右边开始比较样式,删除最短符合样式的字符串

${变量%%样式}:从变量的右边开始比较样式,删除最长符合样式的字符串

${变量/样式/替换字符串}:只替换第一个对比符合样式的字符串

${变量//样式/替换字符串}:替换全部符合样式的字符串

若替换字符串为空则为删除符合样式的字符串,若样式前加#表示该样式必须出现在变量的开头,若加上%表示该样式必须出现在变量的末尾。

若将变量名换为@或者*表示会把各位置参数轮流对比样式进行替换操作。

${!开头字符串@}或者${!开头字符串*}:列出所有以”开头字符串”开头的变量名称,各变量之间用$IFS定义的第一个分隔符隔开。

${!数组[@]}或者${!数组[*]}:列出数组所有的索引,各索引之间用$IFS的第一个分隔符隔开,若将${!数组[@]}用双引号引起来,返回的值不是一个字符串,而是将各个索引值视为单独的字符串。

3、命令替换:将命令执行后的输出放入变量中,会自动删除换行符,有以下两种写法:

变量名称=$(命令)   【推荐写法】

变量名称=`命令`

在获取命令执行结果的时候会自动删除换行符,可用IFS变量替换换行符。

在命令替换里也可以使用其他的命令替换,如r=$(du –s $(pwd))

3,算术扩展:I=$((4+5))会计算值,否则会当成一个字符串,如I=4+5,实际上I的值为“4+5”字符串。

三、 算术运算:常用的几种方法如下

名称

语法

范例

算术扩展

$((算术式))

R=$((3+5*7))

使用外部程序expr

R=`expr 4+5`

R=`expr 4+5`

使用$[ ]

$[算术式]

R=$[4+5]

使用内置命令declare

Declare  –i 变量=算术式

Declare –I r=4+5

使用内置命令let

Let 算术式

Let r=5+4

1,算术式可包含变量、变量扩展,在进行计算时变量会被替换,变量扩展会被展开。

求值时若算术式中的变量不存在或者空值,则该变量的值为0.

0开头为八进制,以0x或者0X开头为16进制,不同进制的数字可以”进制#数字”的表示法。

$((表达式中))如果表达式中的变量,最好不要加$,以免该变量不存在造成语法错误,若表达式中有变量扩展则要加上$,如推荐用$((12+i)),不推荐用$((12+$i))

常用的算术运算符:

++/--自增和自减、*乘、/除、**乘方、%求余、<<位左移、>>位右移、|位或、&位与。

+=-=*=/=等赋值运算符。

三元运算符:((n<100?45:89))

2expr作表达式时,如果达表式中含有bash shell的特殊字符,如*|<>!&()的话要进行转义,否则会错。

r=`expr 参数1\| 参数2`:若参数1存在、非空、非0则传回参数1的值,否则传回参数2的值。

r=`expr 参数1 \& 参数2`:若参数1和参数2都存在、非空、非0,则返回参数1的值,否则返回0

r=`expr 4+5`:加法运算。 r=`expr 4-5`:减法运算。r=`expr 4 \* 5`:乘法运算。

r=`expr 4 % 5`:求余运算。 r=`expr 4 / 5`:除法运算。r=`expr $r+1`:递加1

r=`expr “string”:st`:对比样式st符合的字符数,此处符合2个字符,故r值为2.

r=`expr match “string” st`与上式一样。

r=`expr  index “string”  in`:找出子串在字符串中的位置。此处为3,即instring中的位置为3.

r=`expr  substr  “string”  2  3`:从第2个字符开始取3个字符的长度。

r=`expr  length “string”`:计算字符串的长度。

r=`expr  + match`+后接要视为一般字符的关键词或者运算符,如 等。

r=`expr 1\< 2`成立并返回1r=`expr 3 \<= 2`不成立返回0r=`expr 2=2`成立并返回1

r=`expr 3 \!= 2`成立并返回1r=`expr 3\>= 2`成立并返回1.r=`expr 3 \> 2`成立并返回1

注:expr不支持乘方运算。

3、使用$[ ]做算术运算

r=$[算术式]r=$[4+-*/%5]4加减乘除求余5.

r=$[2**3]乘方运算。r=$[r+1]递加运算。

4、使用内置命令declarelet做算术运算:在用这两个命令时,运算符和操作数之间不可以有空格,要紧密相连。特殊符号不必转义,如乘法*、乘方**直接就可以用,在算式中可以包含其他变量,变量之前不用加$符号。

declare设定变量后运算就比较直观了,如declare –I x.x=5*7x=2**3

let指令也是如此,如let I=6+4;let I=2**3

使用空格符可增强可读性,但这时要加双引号,如let “I = I + 5”

四、 流程控制语句:用breakcontinue语句可跳出循环。

1, if判断语法:

if  条件测试1;then

命令区域1

elif 条件测试2;then

    命令区域2

else

    命令区域3

fi

If  条件测试1

Then

命令区域1

Elif 条件测试2

Then

命令区域2

Else

命令区域3

fi

Ø 这里的条件测试可为一条命令,包括管道命令,执行成功则返回真,如if grep –q “str”                         wendao.txt;then 就是查到wendao.txt里是否包含str这个字符串,若成就判真。

Ø 如if ((a<b));then 这里((算术式))是复合命令的内置算式,它等同于let “算式”:if let “a<b”.

其他的如:((0))((1))((5*6))((20<30))((20&&30))((10&3))((2|5))。结果为0就判断为假,非0就判断为真。

Ø 还可以使用[[ 判断式  ]],注意这里的空格,如if [[ str > xyz ]];then

Ø 使用内置命令:test判断式,如if  test  “str”  \>  “xyz”;then

Ø 使用内置命令:判断式 ],与test用法相同,两者可改写,如if [ “str” \>  “xyz”  ];then

Ø 作用-a-o进行逻辑组合:

[ -r filename1  -a  -x filename1 ]-a有且之意,filename1可读并且可执行时满足条件。

[ -r filename1  -o  -x filename1 ]-o有或之意,filename1可读或者可执行时满足条件。

Ø 命令1  &&  命令2:如果命令1执行成功才会执行命令2,如果两个命令都执行成功返回真值,否则就返回假值。

Ø 命令1  ||  命令2:如果命令1执行失败才会执行命令2,如果两者有一个执行成功就返回真,否则返回假值。

注意:[[  ]] 和 ((  ))都不必转义运算符。在[[  ]]中如果使用==或者!=,且在这两个运算符的右方的字符串没有加上单引号或者双引号,则==或者!=会视为想要对比该字符串所形成的”样式”,如果相符返回真值,如 [[  $a == “???”  ]][[  $a == ???  ]] 是不一样的。其中 =~ 右边放想要对比的正则表达式样式,[[  $a =~  .{3}  ]] 注意此样式不要加引号。

Ø 有关文件属性的判断:

判断式

含义

-a 文件

若文件存在

-b 文件

若文件存在,且该文件是区域设备文件

-c 文件

若文件存在,且该文件是字符设备文件

-d 文件

若文件存在,且该文件是目录

-e 文件

若文件存在

-f 文件

若文件存在,且该文件是一般文件

-g 文件

若文件存在,且设置了set  group  id属性

-h 文件

若文件存在,且是符号链接文件

-k 文件

若文件存在,且设置了sticky位的属性

-p 文件

若文件存在,且是管道文件

-r 文件

若文件存在,且具有可读的属性

-s 文件

若文件存在,且文件大小大于0

-t 文件描述符

若文件描述符是开启的,且链接了某一个终端

-u 文件

若文件存在,且设置了set user id 属性

-w 文件

若文件存在,且具有可写的属性

-x 文件

若文件存在,且具有可执行的权限

-O 文件

若文件存在,且该文件为有效的用户id所拥有

-G 文件

若文件存在,且该文件为有效的群组id所拥有

-L 文件

若文件存在,且为符号链接文件

-S 文件

若文件存在,且为socket文件

-N 文件

若文件存在,且自从上次读取后被修改过

文件–nt 文件2

若文件1比文件2新。或者文件1存在但文件2不存在

文件–ot 文件2

若文件1比文件2旧。或者文件2存在但文件1不存在

文件–ef 文件2

若文件1和文件2链到相同的设备和inode编号

Ø 有关字符串的判断:变量名上最好加双引号,以免变量内容为空时造成语法错误。

判断式

含意

-z 字符串

若字符串长度为0(空串)

-n 字符串

若字符串长度不为0,即非空串

字符串

若字符串长度不为0

字符串1 == 字符串(或者用 

若两个字符串相等

字符串1  !=  字符串2

若两个字符串不相等

字符串1  <  字符串2

若串1小于串2

字符串1  >  字符串2

若串1大于串2

Ø 算式的条件判断:参数1  -eq  参数2

-eq:相等。-ne:不相等。-lt:小于。-gt:大于。-le:小于等于。-ge:大于等于。

Ø bash选项判断式:-o set 选项名称:如果该选项是开启的状态。

2、 case条件判断式的结构如下(相当于其他语言中的switch

Case  待选项  in

      样式串行1)  命令区域1;;

      样式串行2)  命令区域2;;

      样式串行3)  命令区域3;;

      ………….

      *)  命令区域;;

esac

Ø 若样式串行中有好几个字符串要对比,要使用 隔开,为或的意思,只要符合其一就算对比成功。

Ø 样式串行可写成 ‘(样式串行)’ 或者写成 ‘样式串行)’,一般写成后面的。

Ø 样式 串行可包括字符串,如jack。通配符:C*匹配以C开头的字符串。字符集合:[p-r]im表示pimqimrim三个串。

Ø ?(样式串行):匹配0次或者1次样式串行。

*(样式串行):匹配>=0次样式串行。

+(样式串行):匹配>=1次样式串行。

@(样式串行):符合样式串行中的一个就算对比符合。

!(样式串行):只要不是出现在样式串行中的就算对比符合。

以上这些除可用于case语法外,还可以用在[[  ]]判断中,if [[ $cmd == @(declare|export)  ]];then

3、 for循环:串行就是用$IFS所定义的分隔符隔开的字符串组合,以下为两种写法:

For  变量  in  串行

Do

     命令区域

done

IFS=’:’

PL=”root:x:0:0:/bin/bash”

for  f  in  $PL

do 

     echo $f

done

For ((初始条件;  终止条件;  异动项))

Do

命令区域

done

Declare  –i i sum

For ((i=1;i<=20;i=i+1))

Do

     Let sum+=i

done

4、 while循环,语法如下:

While  条件测试

Do 

     命令区域

done

While ((i < 10))

Do

Let ++i

done

While  read  line

Do

     Echo $line

Done < cvsfile

IFS=’:’

While  read  f1 f2 f3 f4 f5 f6 f7

Do

Echo “账号:$f1

Done < “/etc/passwd”

IFS=’:’

Cat  /etc/passwd |{

While  read  f1 f2 f3 f4 f5 f6 f7

Do

     Echo “账号:$f1

done

}

5、 until循环:与while循环刚好相反,当条件测试值为假的时候才会进入循环。

Until  条件测试

Do 

     命令区域

done

6、 select选择列表:

Select  选项变量  in  串行

Do

      命令区域

done

   select命令用来建立一个选项列表,列表提示符由内置变量$PS3定义,默认是#?select会给各选项一个编号,由1开始递增,当健入编号选择其中某一选项时,该选项的内容就赋给选项变量,而健入的编号则赋值给REPLY变量中。

五、 函数:函数名  参数1  参数2  参数3……

Function 函数名()

{

}

函数名()

{

}

Function 函数名

{

}

1、 在使用函数前一定要定义函数,否则会报找不到函数的错误。

2、 在函数执行期间,FUNCNAME表示当前执行的函数,最后一条命令的执行状态代表函数的返回值,如果有return则返回,如return  4 返回4

3、 用unset –f 函数名 取消函数。

4、 函数只在定义的shell中有效,执行时并不开启新的shell环境,若想让定义的函数在子shell中有效,可用内置命令export –f 选项。

5、 如果没有特别指定,在script中定义的变量为全局变量,在整个脚本文件里皆有效,若想定义函数的私有变量,可用local命令,如local var=0,在函数外就访问不了。

6、 当函数借用命令行参数时,原有的位置参数会被保存起来,等函数执行结束后再恢复其值。

7、 各参数变量:$0script文件本身,$1:第一个参数,$2:第二个参数,….$9:第9个参数,${10}10个参数,$#:参数的个数,$@:所有以空白隔开的参数,$*:所有的参数组成的字符串。

六、输出转向操作:

1,操作系统默认指定的3个文件代码:0标准输入(stdin)1标准输出(stdout)2标准错误(stderr),转向时 代表转向输入,若<左方的文件代码省略默认为0即标准输入,代表转向输出,若>左方的文件代码省略,默认为1即标准输出。

2,开启文件,fnu<>文件,开启一个文件,指定其文件代码为fnu,如exec  6<>test.txt开启文件test.txt并指定其文件代码为6

3,关闭文件,fnu<&- 关闭转向输入文件,如 exec  6<&- 关闭文件代码6fnu>&- 关闭转向输出文件,如exec  5>&- 关闭文件代码5

4,复制文件代码,有时为了不影响原有文件代码的使用最好先复制一份,等操作结束再还原回去。

n<&m 复制转向输入的文件代码m,存成文件代码n,使n连接至m

n>&m 复制转向输出的文件代码m,存成文件代码n,使n连接至m

exec  >&6 将标准输出连接至代码6,凡是原本在标准输出的内容全转存至文件代码6

cat  <&6  将文件代码6的内容转向至标准输入,并有cat把内容显示出来。

exec  5<&0 复制标准输入存成文件代码5,建立文件代码0的连接,就是做输入的备份,一旦备份好后就可以对标准输入进行操作,如转向输入,操作完后应还原标准输入,如  exec  0<&5  5<&- :还原并关闭连接。

 5,转向输入:

 fnu<文件:wc –l  </etc/error.log此处fnu默认为0即标准输入,将标准输入和error.log建立链接,wc改由error.log读取行数。wc并不知道它是从哪里取得数据,反正wc默认就是从标准输入读取数据。

 exec  6< /etc/error.log 

 wc –l  <&6

使用文件代码6作输入,来源是error.log,由文件代码6供应wc数据行。

6,转向输出:

fnu>文件:使用文件做转向输出,若文件不存在则创建一个新文件,若存在则清空文件。fnu省略的话默认为1.如产生空文件可以用 > test.txt或者:> test.txt

fnu >| 文件:此语法不理会noclobber选项,只要文件存在就强制覆盖并清空该文件。

7,转向附加: fun>>文件,若文件存在,就写在文件后面,不会清空文件。

8,标准错误伴随标准输出做转向:&>文件  或者  >&文件

ntpdate  time.stdtime.gov.cn  &>/dev/null 

使用ntpdatentp主机校时,如果执行时产生错误信息,则伴随执行过程产生的信息,转向输出至/dev/null,即屏弃错误信息。

&>的作用和 “ >文件  2>&1”的作用是相同的,意为转向输出至文件,标准错误代码2连接至标准输出1,如上例可写为:ntpdate time.stdtime.gov.cn  > /dev/null  2>&1

9,Here  Document的转向:

exec  6<<wendao

line1

line2

wendao  

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值