Shell基础

Shell基础

Shell脚本文件第一行 #!/bin/bash,用于告诉系统解释此脚本文件的Shell程序。常见的Shell程序有Bourne Shell(/bin/sh)和Bourne Again Shell(/bin/bash)。
脚本文件的扩展名不影响脚本执行。
运行 Shell 脚本有两种方法:

  1. 作为可执行程序
chmod +x ./test.sh  #使脚本具有执行权限
./test.sh  #执行脚本

注意,一定要写成 ./test.sh,告诉系统在当前目录找该文件,否则系统会去PATH里寻找test.sh,而只有/bin, /sbin, /usr/bin/usr/sbin 等会在PATH里。

  1. 作为解释器参数
/bin/sh test.sh

此时,文件中的第一行指定的解释器信息是无效的。

双击tab键可补全命令
history可以查看命令历史
使用env命令可列出系统预设的全部环境变量,通常预设的变量都是大写的,如PATH
通过echo $PATH可显示变量的值。
常见的环境变量有:

PATH 决定了shell将到哪些目录中寻找命令或程序
HOME 当前用户主目录
HISTSIZE 历史记录数
LOGNAME 当前用户的登录名
HOSTNAME 指主机的名称
SHELL 前用户Shell类型
LANG 语言相关的环境变量,多语言可以修改此环境变量
MAIL 当前用户的邮件存放目录
PWD 当前目录

使用set命令可列出系统预设的全部变量及用户自定义变量。
设定变量的格式为a=b,其中a为变量名,b为变量的内容,等号两边不能有空格;
想取消某个变量,只要输入unset 变量名即可。
需要注意的是,用户自定义变量只在当前shell生效。

dylan@DESKTOP-FRA3DA2:~$ myvar=MyVar
dylan@DESKTOP-FRA3DA2:~$ echo $myvar
MyVar
dylan@DESKTOP-FRA3DA2:~$ bash #通过bash命令打开一个新的bash
dylan@DESKTOP-FRA3DA2:~$ echo $myvar

dylan@DESKTOP-FRA3DA2:~$ exit #退出当前shell,回到旧的shell
exit
dylan@DESKTOP-FRA3DA2:~$ echo $myvar
MyVar
dylan@DESKTOP-FRA3DA2:~$

如果要永久生效,依据生效的范围不同,如下:

  • 要想系统内所有用户登录后都能使用该变量
    需要在/etc/profile文件最末行加入export myvar=MyVar然后运行source /etc/profile就可以生效了。
  • 只想让当前用户使用该变量
    需要在用户主目录下的.bashrc文件最后一行加入export myvar=MyVar然后运行source .bashrc就可以生效了。

如果在当前shell中运行bash指令后,则会进入一个新的shell,这个shell就是原来shell的子shell了,可用pstree指令来查看。pstree这个指令会把linux系统中所有进程通过树形结构打印出来。

dylan@DESKTOP-FRA3DA2:~$ pstree
init─┬─init───bash───su───bash───su───bash───pstree
     └─{init}

在父shell中设定一个变量后,进入子shell后该变量是不会生效的,如果想让这个变量在子shell中生效则要用到export指令:

dylan@DESKTOP-FRA3DA2:~$ myvar=MyVar
dylan@DESKTOP-FRA3DA2:~$ echo $myvar
MyVar
dylan@DESKTOP-FRA3DA2:~$ bash
dylan@DESKTOP-FRA3DA2:~$ echo $myvar

dylan@DESKTOP-FRA3DA2:~$ exit
exit
dylan@DESKTOP-FRA3DA2:~$ export myvar
dylan@DESKTOP-FRA3DA2:~$ bash
dylan@DESKTOP-FRA3DA2:~$ echo $myvar
MyVar

几个重要文件:

系统级别:
/etc/profile:这个文件预设了几个重要的变量,例如PATH, USER, LOGNAME, MAIL, INPUTRC, HOSTNAME, HISTSIZE, umas等等。
/etc/bashrc :这个文件主要预设umask以及PS1PS1是指命令提示符,如 dylan@DESKTOP-FRA3DA2:~$
用户级别,在用户目录下:
.bash_profile:定义了用户的个人化路径与环境变量的文件名称。每个用户都可使用该文件输入专用于自己使用的shell信息,当用户登录时,该文件仅仅执行一次。
.bashrc:该文件包含专用于你的shell的bash信息,当登录时以及每次打开新的shell时,该该文件被读取。例如你可以将用户自定义的alias或者自定义变量写到这个文件中。
.bash_history:记录命令历史用的。
.bash_logout :当退出shell时,会执行该文件。可以把一些清理的工作放到这个文件中。

常用命令:

  • cut 截取某一个字段

语法:cut -d “分隔字符” [-cf] n #这里的n是数字
-d:后面跟分隔字符,分隔字符要用双引号括起来
-c:后面接的是第几个字符
-f:后面接的是第几个区块

root@DESKTOP-FRA3DA2:~# cat /etc/passwd | cut -d ":" -f 1
root
daemon
bin
...

root@DESKTOP-FRA3DA2:~# cat /etc/passwd | cut -d ":" -f 2
x
x
x
...

root@DESKTOP-FRA3DA2:~# cat /etc/passwd | cut -c 1
r
d
b
...

root@DESKTOP-FRA3DA2:~# cat /etc/passwd | cut -c 1,4
rt
dm
b:
...

root@DESKTOP-FRA3DA2:~# cat /etc/passwd | cut -c 1-4
root
daem
bin:
...
  • sort 排序

语法:sort [-t 分隔符] [-kn1,n2] [-nru],这里的n1 < n2
-t 分隔符
-n:使用纯数字排序
-r:反向排序
-u:去重复
-kn1,n2 :由n1区间排序到n2区间,可以只写-kn1,即对n1字段排序

root@DESKTOP-FRA3DA2:~# cat /etc/passwd | sort
_apt:x:104:65534::/nonexistent:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
...

root@DESKTOP-FRA3DA2:~# cat /etc/passwd | sort -t: -k3n
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
...

root@DESKTOP-FRA3DA2:~# cat /etc/passwd | sort -t: -k3nr
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
una:x:1002:1002::/home/una:/bin/bash
chan:x:1001:1001::/home/chan:/bin/bash
...

root@DESKTOP-FRA3DA2:~# cat /etc/passwd | sort -t: -k3,5n
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
...
  • wc 统计文档的行数、字符数、词数

-l:统计行数
-m:统计字符数
-w:统计词数

dylan@DESKTOP-FRA3DA2:~/test$ echo "hello world" > test.txt
dylan@DESKTOP-FRA3DA2:~/test$ echo "hello world again" >> test.txt
dylan@DESKTOP-FRA3DA2:~/test$ cat test.txt | wc -l
2
dylan@DESKTOP-FRA3DA2:~/test$ cat test.txt | wc -w
5
dylan@DESKTOP-FRA3DA2:~/test$ cat test.txt | wc -m
30
  • uniq 去重复的行

-c:统计重复的行数,并把行数写在前面

dylan@DESKTOP-FRA3DA2:~/test$ cat test.txt
hello world
hello world again
hello world again
dylan@DESKTOP-FRA3DA2:~/test$ cat test.txt | sort | uniq
hello world
hello world again
dylan@DESKTOP-FRA3DA2:~/test$ cat test.txt | sort | uniq -c
      1 hello world
      2 hello world again

注意:在进行uniq之前,需要先用sort排序然后才能uniq

  • tee 后跟文件名,类似与重定向">",但是比重定向多了一个功能,在把文件写入后面所跟的文件中的同时,还显示在屏幕上。
dylan@DESKTOP-FRA3DA2:~/test$ echo "hello world again" | tee test.txt
hello world again
dylan@DESKTOP-FRA3DA2:~/test$ cat test.txt
hello world again
  • split 切割文档

-b :依据大小来分割文档,单位为byte
-l :依据行数来分割文档

dylan@DESKTOP-FRA3DA2:~/test$ ll
total 0
drwxr-xr-x 1 dylan dylan 512 Sep 23 14:44 ./
drwxr-xr-x 1 dylan dylan 512 Sep 23 10:54 ../
-rw-rw-r-- 1 dylan dylan  90 Sep 23 14:42 test.txt
-rw-r--r-- 1 dylan dylan   0 Sep 22 19:25 test_file.txt
-rwxr-xr-x 1 dylan dylan 129 Sep 22 11:36 test_shell.bash*
dylan@DESKTOP-FRA3DA2:~/test$ split -b 30 test.txt test
dylan@DESKTOP-FRA3DA2:~/test$ ll
total 0
drwxr-xr-x 1 dylan dylan 512 Sep 23 14:44 ./
drwxr-xr-x 1 dylan dylan 512 Sep 23 10:54 ../
-rw-rw-r-- 1 dylan dylan  90 Sep 23 14:42 test.txt
-rw-r--r-- 1 dylan dylan   0 Sep 22 19:25 test_file.txt
-rwxr-xr-x 1 dylan dylan 129 Sep 22 11:36 test_shell.bash*
-rw-rw-r-- 1 dylan dylan  30 Sep 23 14:44 testaa
-rw-rw-r-- 1 dylan dylan  30 Sep 23 14:44 testab
-rw-rw-r-- 1 dylan dylan  30 Sep 23 14:44 testac
dylan@DESKTOP-FRA3DA2:~/test$ cat testaa
hello world again
hello world dylan@DESKTOP-FRA3DA2:~/test$


dylan@DESKTOP-FRA3DA2:~/test$ cat test.txt
hello world again 1
hello world again 2
hello world again 3
hello world again 4
hello world again 5
dylan@DESKTOP-FRA3DA2:~/test$ split -l 3 test.txt testl
dylan@DESKTOP-FRA3DA2:~/test$ ll
total 0
drwxr-xr-x 1 dylan dylan 512 Sep 23 14:48 ./
drwxr-xr-x 1 dylan dylan 512 Sep 23 14:48 ../
-rw-rw-r-- 1 dylan dylan 100 Sep 23 14:48 test.txt
-rw-r--r-- 1 dylan dylan   0 Sep 22 19:25 test_file.txt
-rwxr-xr-x 1 dylan dylan 129 Sep 22 11:36 test_shell.bash*
-rw-rw-r-- 1 dylan dylan  30 Sep 23 14:44 testaa
-rw-rw-r-- 1 dylan dylan  30 Sep 23 14:44 testab
-rw-rw-r-- 1 dylan dylan  30 Sep 23 14:44 testac
-rw-rw-r-- 1 dylan dylan  60 Sep 23 14:48 testlaa
-rw-rw-r-- 1 dylan dylan  40 Sep 23 14:48 testlab
dylan@DESKTOP-FRA3DA2:~/test$ cat testlaa
hello world again 1
hello world again 2
hello world again 3
  • grep 查找

语法:grep [-cinvABC] ‘word’ filename
-c:打印符合要求的行数
-i:忽略大小写
-n:在输出符合要求的行的同时连同行号一起输出
-v:打印不符合要求的行
-A:后跟一个数字(有无空格都可以),例如 –A2则表示打印符合要求的行以及下面两行
-B:后跟一个数字,例如 –B2 则表示打印符合要求的行以及上面两行
-C:后跟一个数字,例如 –C2 则表示打印符合要求的行以及上下各两行

grep

egrepgrep的扩展版,支持’+’(匹配1次或多次),’?’(匹配0次或1次),’|’,’()’(分组)这几个规则
egrep

Shell编程基础

1. Shell变量

  • 定义变量如下:
my_var="abc"

需要注意的是,变量名与等号之间不能有空格;变量的命名只能使用字母、数字及下划线,且首个字符不能为数字;不能使用空格、标点符号及bash中的关键字。
使用变量:

echo ${my_var}

注意,需要在变量名前加"$",另外,花括号是可选的,用于某些情况用于区分边界,良好的习惯是加上{}。

  • 只读变量:
    通过readonly命令可以将变量定义为只读变量,该变量的值不能改变,例如:
readonly my_var
  • 删除变量:
    使用unset命令可以将变量删除,例如:
unset my_var

注意,unset命令不能删除只读变量

  • 变量类型:
  • 局部变量 在脚本中定义且只在当前实例中生效
  • 环境变量 所有的程序,包括Shell启动的程序,都能访问环境变量
  • Shell变量 Shell变量是由Shell程序设置的特殊变量

2. 字符串:

可用单引号、双引号或者不适用引号。
单引号与双引号的区别:
单引号中不能出现单独的一个单引号(’),即使转义也不行;单引号中的变量智慧原样输出而不能转化为变量值输出。需要注意,var1='hello, '$my_var'!'中的my_var是可以转化为变量值的,但var2='hello, ${my_var}!'则不行。
双引号中可以出现转义字符;双引号中的变量可以转化成变量值。

  • 字符串拼接:

通过单引号拼接:

var1='hello, '$my_var'!'
var2='hello, ${my_var}!'

通过双引号拼接:

var3="hello, "$my_var"!"
var4="hello, ${my_var}!"
  • 字符串的长度:
echo ${#my_var} #输出3
  • 字符串提取子字符串:
echo ${#my_var:1:2} #输出bc,表示从第2个字符开始截取2个字符
  • 查找子字符串:
string="this is for test"
echo `expr index "$string" io` #输出3,此处表示查找i或o的位置,哪个先出现就计算哪个的

3. Shell数组:

注意,bash仅支持一维数组,数组下标从0开始,初始化时不需要定义数组大小。

  • 数组赋值:
1 array_name=(v1 v2 v3)或
  array_name=(
  v1
  v2
  v3
  )
2 array_name[0]=v1
  array_name[1]=v2
  array_name[2]=v3
  • 数组读取:
1 ${array_name[n]}
2 ${array_name[@]} # 获取所有元素
  • 数组长度:
1 ${#array_name[@]} # 取得数组元素的个数
2 ${#array_name[*]} # 取得数组元素的个数
3 ${#array_name[n]} # 取得数组下标为n的元素的长度

4. 注释:

  • 单行注释,以#开头
  • 多行注释,如下:
 :<<EOF
  注释内容...
  EOF

5. Shell传递参数:

在执行Shell脚本时可以传参数,在脚本中用$n获取,$0表示当前脚本文件的名称,$1表示第1个参数,以此类推。
另外,
$#,表示传递的参数的个数;
$*,以一个字符串接受所有参数,如果是"$*",则以"$1 $2 ..."形式输出;
$@,同上,不同的是,如果是"$@",则以"$1" "$2" 形式输出;
$$,表示脚本运行的当前进程ID号;
$!,表示后台运行的最后一个进程的ID号;
$-,显示Shell使用的当前选项,与set命令功能相同。
$?,显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。

6. Shell运算符:

  • 数学运算
    原生bash不支持简单的数学运算,可通过expr表达式计算工具来实现,如下:
val1=`expr $a + $b`
val2=`expr $a - $b`
val3=`expr $a \* $b`
val4=`expr $a / $b`
val5=`expr $a % $b`

注意:表达式和运算符之间要有空格;完整的表达式要被 `` 包含;乘法"*“需要转义符号”\"。

  • 关系运算:
    == 用于比较两个数字是否相等,相同则返回true。[ $a == $b ]返回false
    != 用于比较两个数字是否不相等,不相同则返回true。[ $a != $b ]返回true
    -eq 检测两个数是否相等,相等返回true。[ $a -eq $b ]
    -ne 检测两个数是否不相等,不相等返回true。[ $a -ne $b ]
    -gt 检测左边的数是否大于右边的,如果是,则返回true。[ $a -gt $b ]
    -lt 检测左边的数是否小于右边的,如果是,则返回true。[ $a -lt $b ]
    -ge 检测左边的数是否大于等于右边的,如果是,则返回true。[ $a -ge $b ]
    -le 检测左边的数是否小于等于右边的,如果是,则返回true。[ $a -le $b ]
    注意:条件表达式要放在方括号之间,并且要有空格。
  • 布尔运算:
    ! 非运算,表达式为true则返回false,否则返回true。[ ! false ]
    -o 或运算,有一个表达式为true则返回true。[ $a -lt 20 -o $b -gt 100 ]
    -a 与运算,两个表达式都为true才返回true。[ $a -lt 20 -a $b -gt 100 ]
  • 逻辑运算符:
    && 逻辑的AND,[[ $a -lt 100 && $b -gt 100 ]]
    || 逻辑的OR,[[ $a -lt 100 || $b -gt 100 ]]
  • 字符串运算符:
    = 检测两个字符串是否相等,相等返回true。[ $a = $b ]
    != 检测两个字符串是否相等,不相等返回true。[ $a != $b ]
    -z 检测字符串长度是否为0,为0返回true。[ -z $a ]
    -n 检测字符串长度是否不为 0,不为0返回true。[ -n $a ]
    $ 检测字符串是否为空,不为空返回true。[ $a ]
    实例:
#!/bin/bash

a=10
b=20
# 关系运算
if [ $a -eq $b ]
then
   echo "$a -eq $b : a 等于 b"
else
   echo "$a -eq $b: a 不等于 b"
fi
# 布尔运算
if [ $a -lt 100 -a $b -gt 15 ]
then
   echo "$a 小于 100 且 $b 大于 15 : 返回 true"
else
   echo "$a 小于 100 且 $b 大于 15 : 返回 false"
fi
# 逻辑运算
if [[ $a -lt 100 && $b -gt 100 ]]
then
   echo "返回 true"
else
   echo "返回 false"
fi

7. Shell echo命令:

用于字符串的输出,输出字符串时,双引号可加可不加;
可以显示转义字符;
可以显示变量;原样输出变量时,用单引号;
可显示换行(\n)与不换行(echo -e "\c", -e 开启转义 \c 不换行);
可将显示结果定向至文件;
可显示命令执行结果,echodate(显示当前日期)。

8. read可用于接受标准输入,read var将标准输入赋值给var。

9. printf

默认printf不会像echo自动添加换行符,我们可以手动添加\n
printf命令的语法:

printf format-string [arguments...]

其中,format-string如下:
%s %c %d %f都是格式替代符。
%-10s 指一个宽度为10个字符(-表示左对齐,没有则表示右对齐),任何字符都会被显示在10个字符宽的字符内,如果不足则自动以空格填充,超过也会将内容全部显示出来。
%-4.2f 指格式化为小数,其中.2指保留2位小数,4同上表示字符宽度。
更多实例:

# format-string为双引号
printf "%d %s\n" 1 "abc"
# 单引号与双引号效果一样 
printf '%d %s\n' 1 "abc" 
# 没有引号也可以输出
printf %s abcdef
# 格式只指定了一个参数,但多出的参数仍然会按照该格式输出,format-string 被重用
printf %s abc def
printf "%s\n" abc def
printf "%s %s %s\n" a b c d e f g h i j
# 如果没有 arguments,那么 %s 用NULL代替,%d 用 0 代替
printf "%s and %d \n" 
输出结果:
1 abc
1 abc
abcdefabcdefabc
def
a b c
d e f
g h i
j  
 and 0

10. test

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

num1=100
num2=100
if test $[num1] -eq $[num2]
then
    echo '两个数相等!'
else
    echo '两个数不相等!'
fi

其中,

-eq等于则为真
-ne不等于则为真
-gt大于则为真
-ge大于等于则为真
-lt小于则为真
-le小于等于则为真

注意,$[num1]中的[]执行基本的算数运算,即此处num1可替换成$[50+50],注意等号两边不能有空格

字符串测试:

num1="ru1noob"
num2="runoob"
if test $num1 = $num2
then
    echo '两个字符串相等!'
else
    echo '两个字符串不相等!'
fi

其中,

=等于则为真
!=不相等则为真
-z 字符串字符串的长度为零则为真
-n 字符串字符串的长度不为零则为真

文件测试:

if test -e ./bash
then
    echo '文件已存在!'
else
    echo '文件不存在!'
fi

其中,

-e 文件名如果文件存在则为真
-r 文件名如果文件存在且可读则为真
-w 文件名如果文件存在且可写则为真
-x 文件名如果文件存在且可执行则为真
-s 文件名如果文件存在且至少有一个字符则为真
-d 文件名如果文件存在且为目录则为真
-f 文件名如果文件存在且为普通文件则为真
-c 文件名如果文件存在且为字符型特殊文件则为真
-b 文件名如果文件存在且为块特殊文件则为真

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

if test -e ./notFile -o -e ./bash
then
    echo '至少有一个文件存在!'
else
    echo '两个文件都不存在'
fi

11. 流程控制:

  • if语句:
if condition
then
    command1 
    command2
    ...
    commandN
else
    command
fi
  • for循环:
for var in item1 item2 ... itemN
do
    command1
    command2
    ...
    commandN
done
  • while语句:
while condition
do
    command
done
  • util循环:
until condition
do
    command
done
  • case:
case 值 in
模式1)
    command1
    command2
    ...
    commandN
    ;;
模式2)
    command1
    command2
    ...
    commandN
    ;;
esac

取值后面必须为单词in,取值可以为变量或常数。
每一模式必须以右括号结束,模式支持正则表达式。
匹配发现取值符合某一模式后,其间所有命令开始执行直至";;",";;"表示 break。

12. Shell函数:

  • 函数定义
[function] funname() {
	var=100
	do sth
	return $var 
}

function可省略,可用return显式返回结果,否则则返回最后一条命令的结果。
通过函数名funname即可调用函数,函数返回值再调用函数后通过$?来获取。
在Shell中,调用函数时可以向其传递参数。在函数体内部,通过$n的形式来获取参数的值,例如,$1表示第一个参数,$2表示第二个参数,当n>=10时,需要使用${n}来获取参数。此处同“Shell传递参数”。

13. 重定向:

一般情况下,每个 Unix/Linux 命令运行时都会打开三个文件:
标准输入文件(stdin):stdin的文件描述符为0,Unix程序默认从stdin读取数据。
标准输出文件(stdout):stdout 的文件描述符为1,Unix程序默认向stdout输出数据。
标准错误文件(stderr):stderr的文件描述符为2,Unix程序会向stderr流中写入错误信息。
默认情况下,command > filestdout重定向到filecommand < filestdin重定向到file。

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

$ command 2 > file

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

$ command 2 >> file

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

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

$ command > file 2>&1

或者

$ command >> file 2>&1

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

$ command < file1 > file2

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

Here Document是Shell中的一种特殊的重定向方式,用来将输入重定向到一个交互式Shell脚本或程序。
它的基本的形式如下:

command << delimiter
    document
delimiter

它的作用是将两个delimiter(分隔符)之间的内容(document) 作为输入传递给command
注意:
结尾的delimiter一定要顶格写,前面不能有任何字符,后面也不能有任何字符,包括空格和tab缩进。
开始的delimiter前后的空格会被忽略掉。

$ wc -l << EOF
    111
    222
    333
EOF
3    # 输出结果为 3 行

如果希望执行某个命令,但又不希望在屏幕上显示输出结果,那么可以将输出重定向到/dev/null
/dev/null 是一个特殊的文件,写入到它的内容都会被丢弃;如果尝试从该文件读取内容,那么什么也读不到。
如果希望屏蔽 stdoutstderr,可以这样写:

$ command > /dev/null 2>&1

14. 文件包含:

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

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

source filename

注:被包含的文件filename不需要可执行权限。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值