linux基本命令整理——鸟哥linux私房菜第十二章

Shell Scripts
shell script 有点像是早期的批处理文件,亦即是将一些指令汇整起来一次执行,但是 Shell script 拥有更强大的功能,那就是他可以进行类似程序 (program) 的撰写,并且不需 要经过编译 (compile) 就能够执行, 真的很方便。

如果写了一个程序文件/home/dmtsai/shell.sh,如何执行这个文件呢?有下面几个方法。
在这里插入图片描述

#第一支script
mkdir bin; cd bin
vim hello.sh
#然后编辑这个文件输入以下的内容(第一行必须要设置好)
#!/bin/bash
#Program:
#	This program shows "Hello world" in your screen.
#History:
#2021/12/27 VBird First release
PATH=/bin:/sbin:/usr/bin:usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
echo -e "Hello world! \a \n"
exit 0
#然后保存一下,执行该文件看看结果
sh hello.sh
#另外,下面两个也可以执行这个文件
chmod a+x hello.sh
./hello.sh

简单范例

#对谈式脚本:变量内容由使用者决定
#撰写一个脚本,使用者输入first name和last name,在屏幕上显示"Your full name is XXX"
vim showname.sh
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
read -p "please input your first name: " firstname
read -p "please input your last name: " lastname
echo -e "\nYour full name is : ${firstname} ${lastname}"

./showname.sh
#随日期变化:利用date进行文件的创建
#假设我想要创建三个空文件(通过touch),文件名开头由使用者输入决定,如果想要用前天,昨天,今天的日期来命名这些文件,该如何是好?
vim create_3_filename.sh
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
#1\.让使用者输入文件名称,并取得fileuser这个变量
#纯粹显示一行提示信息
echo -e "I will use 'touch' command to create 3 files."
#提示使用者输入
read -p "Please input your filename: " fileuser

#2\.为了避免使用者随意按Enter,利用[变量功能](../Text/index.HTML#variable_other_re)分析文件名
filename=${filuser:-"filename"}#也就是fileuser的默认值是filename

#3\.开始利用date指令取得所需要的文件名
#其中,$(command) 有取得讯息、变量的设置功能、变量的累加以及touch指令辅助。
date1=$(date --date='2 days ago' +%Y%m%d)#前两天的日期
date2=$(date --date='1 days ago' +%Y%m%d)#前一天的日期
date3=$(date +%Y%m%d) #今天的日期
file1=${filename}${date1}
file2=${filename}${date2}
file3=${filename}${date3}

#4\.将文件名创建
touch "${file1}"
touch "${file2}"
touch "${file3}"
#数值计算:简单的加减乘除
vim multiplying.sh
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
echo -e "You should input 2 numbers; Program will cross these 2 numbers."
read -p "first number: " firstnu
read -p "second number: " secnu
#法1
total=$((${firstnu}*${secnu}))
#法2
declare -i total=${firstnu}*${secnu}
echo -e "\nThe result of ${firstnu} x ${secnu} is ${total}"

下面这种方式计算还是挺方便的

echo $((13%3))

如果想计算含有小数点的数据时,可以通过bc这个指令的协助

echo "123.123*55.9" | bc
#数值计算:通过bc计算pi
#计算pi时,小数点以下的位数可以无限制的延伸下去,bc提供了一个运算pi的函数,通过bc -l来调用,接下来编写一个脚本让使用者输入小数点位数,得到对应的Pi值
vim cal_pi.sh
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
echo -e "This program will calculate pi value. \n"
echo -e "You should input a float number to calculate pi value.\n"
read -p "The scale number (10-10000) ? " checking
num=${checking:-"10"}#默认是10
echo -e "Starting calculate pi value. Be patient."
time echo "scale=${num}; 4*a(1)" | bc -lq

script的执行方式差异
1、利用直接执行的方式来执行script
bash xx.sh
sh xx.sh
相对路径./xx.sh
绝对路径
这种情况下执行会重开一个bash,script实际上是在子程序的bash内执行的。当子程序完成后,在子程序内的各项动作或变量会结束而不会传回到父程序中。
2、利用source来执行脚本:在父程序中执行
source xx.sh
此时在程序中设置的变量在当前窗口都是可以echo到的

判断式

利用test指令的测试功能

#检查/dmtsai是否存在
test -e /dmtsai#这样直接执行不会显示任何讯息,可以结合&&||等展现结果
test -e /dmtsai && echo 'exist' || echo "Not exist"

除了测试是否存在之外,还可以进行以下测试
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
接下来举几个test的简单例子
首先,判断一下,让使用者输入一个文件名,我们判断:
1、 这个文件是否存在,若不存在则给予一个“Filename does not exist”的讯息,并中断程序;
2、 若这个文件存在,则判断他是个文件或目录,结果输出“Filename is regular file”或 “Filename is directory”
3、 判断一下,执行者的身份对这个文件或目录所拥有的权限,并输出权限数据!

vim file_perm.sh
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
#1\.让使用者输入文件名,并判断使用者是否真的有输入字串
echo -e "Please input a filename, I will check the filename's type and permission. \n\n"
read -p "Input a filename:" filename
test -z ${filename} && echo "You must input a filename." && exit 0
#2\.判断文件是否存在,若不存在则显示讯息并结束脚本
test ! -e ${filename} && echo "The filename '${filename}' do not exist" && exit 0
#3\.开始判断文件类型与属性
test -f ${filename} && filetype="regulare file"
test -d ${filename} && filetype="directory"
test -r ${filename} && perm='readable'
test -w ${filename} && perm=${perm} writable
test -x ${filename} && perm=${perm} executable
#4\.开始输出信息
echo "The filename: ${filename} is a ${filetype}"
echo "And the permissions for you are : ${perm}"

利用判断符号[ ]
如果想知道${HOME}这个变量是否为空,可以用下面的命令
[ -z “${HOME}” ] ; echo $?
需要注意的是,因为中括号用在很多地方,包括万用字符与正则表达式等,所以如果要在bash中的语法当中使用中括号作为shell的判断式时,需要加空白键,需要注意以下几点:
1、在中括号 [] 内的每个元件都需要有空白键来分隔;
2、在中括号内的变量,最好都以双引号括号起来;
3、在中括号内的常数,最好都以单或双引号括号起来
中括号的使用方法与test几乎一模一样,只是中括号比较常用在条件判断式if…then的情况中。

接下来做一个小案例
1、 当执行一个程序的时候,这个程序会让使用者选择 Y 或 N ,
2、如果使用者输入 Y 或 y 时,就显示“ OK, continue ”
3、 如果使用者输入 n 或 N 时,就显示“ Oh, interrupt !”
4、 如果不是 Y/y/N/n 之内的其他字符,就显示“ I don’t know what your choice is ”

vim ans_yn.sh
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH

read -p "Please input (Y/N): " yn
[ "${yn}"=="Y" -o "${yn}"=="y" ] && echo "OK,continue" && exit 0
[ "${yn}"=="N" -o "${yn}"=="n" ] && echo "Oh,interrupt" && exit 0
echo "I don't know what your choice is" && exit 0

Shell script的默认变量($0,$1)

如果想重新启动系统的网络,可以使用下面的命令
file /etc/init.d/network#首先查询一下发现它是一个bash的可执行脚本
/etc/init.d/network restart#这个可以重新启动
/etc/init.d/network stop#这个可以关闭网络服务

之前,如果要依据程序的执行给予一些变量不同的任务时,使用的是read功能,但read的问题是需要手动从键盘输入一些判断式。如果通过指令后面接参数, 那么一个指令就能够处理完毕而不需要手动再次输入一些变量行为!这样 下达指令会比较简单方便啦!

其实 script 针对参数已经有设置好一些变量名称了!对应如 下:
在这里插入图片描述
?执行的脚本文件名为 $0 这个变量,第一个接的参数就是 $1 ,接着就是$2$3这些
在这里插入图片描述
然后做一个小案例,假设我要执行一个可以携带参数的 script ,执行该脚本后屏幕会显示如下的数据:
程序的文件名为何?
共有几个参数?
若参数的个数小于 2 则告知使用者参数数量太少
全部的参数内容为何?
第一个参数为何?
第二个参数为何?

vim how_paras.sh

#!/bin/bash
PATH=/bin:/sbin:/usr/bin:usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH

echo "The script name is ${0}"
echo "Total parameter number is $#"
[ "$#" < 2 ] && echo "The number of parameter is less than 2\. Stop here." && exit 0
echo "Your whole parameter is $@"
echo "The 1st parmeter : ${1}"
echo "The 2nd parmeter : ${2}"

#调用上面的脚本
sh how_paras.sh theone haha quot

shift:造成参数变量号码偏移
把上面的内容稍微改一下,用来显示每次偏移后参数的变化

vim shift_paras.sh

#!/bin/bash
PATH=/bin:/sbin:/usr/bin:usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH

echo "Total parameter number is $#"
echo "Your whole parameter is $@"
shift #进行第一次一个变量的偏移
echo "Total parameter number is $#"
echo "Your whole parameter is $@"
shift 3 #进行第二次三个变量的偏移
echo "Total parameter number is $#"
echo "Your whole parameter is $@"

#调用上面的脚本执行
sh shift_paras.sh one two three four five six

条件判断式

利用if…then
单层、简单条件判断式

if [条件判断式]; then
		当条件判断式成立时,可以进行的指令工作内容
fi  #结束if

条件判断式可以多个括号写然后彼此之间用&&或||隔开,分别表示AND和OR,所以,此时&&和||与指令下达时不同
[ “${yn}” == “Y” -o “${yn}” == “y” ]可替换为
[ “${yn}” == “Y” ] || [ “${yn}” == “y” ]

#使用if...then的一个样例
cp ans_yn.sh ans_yn-2.sh
vim ans_yn-2.sh
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH

read -p "Please input (Y/N) : " yn
if [ "${yn}" == "Y" ] || [ "${yn}" == "y" ]; then
	echo "OK,continue"
	exit 0
fi
if [ "${yn}" == "N" ] || [ "${yn}" == "n" ]; then 
	echo "Oh,interrupt!"
	exit 0
fi
echo "I don't know what your choice is" && exit 0

多重、复杂条件判断式
if [条件表达式]; then
当条件判断式成立时,可以进行的指令工作内容
else
当条件判断式不成立时,可以进行的指令工作内容
fi
若是有更复杂的情况,多个分支
if [条件表达式1]; then
当条件判断式1成立时,可以进行的指令工作内容
elif [条件表达式2]; then
当条件判断式1成立时,可以进行的指令工作内容
else
当条件判断式1和2均不成立时,可以进行的指令工作内容
fi

cp ans_yn-2.sh ans_yn-3.sh
vim ans_yn-3.sh
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH

read -p "Please input (Y/N): " yn

if [ "${yn}" == "Y" ] || [ "${yn}" == "y" ]; then
	echo "OK,continue"
elif [ "${yn}" == "N" ] || [ "${yn}" == "n" ]; then 
	echo "Oh,interrupt!"
else
	echo "I don't know what your choice is"
fi

再来一个例子,使用上面的if elif 啥的

vim hello-2.sh
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH

if [ "${1}" == "hello" ]; then
	echo "Hello, how are you ? "
elif [ "${1}" == "" ]; then
	echo "you must input parameters"
else
	echo "The only parmeter is 'hello'"
fi

再来一个例子:输入退伍日期,计算还有几天退伍
由于日期是要用相减的方式来处置,所以我们可以通过使用 date 显示日期与时间,将他转为 由 1970-01-01 累积而来的秒数, 通过秒数相减来取得剩余的秒数后,再换算为日数即可。 整个脚本的制作流程有点像这样:
1、 先让使用者输入他们的退伍日期;
2.、再由现在日期比对退伍日期;
3、 由两个日期的比较来显示“还需要几天”才能够退伍的字样。

vim cal_retired.sh
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
#1\.告知使用者这支程序的用途,并且告知应该如何输入日期格式
echo "This program will try to calculate:"
echo "How mny days before your demobilization date..."
read -p "Please input your demobilization date (YYYYMMDD):" date2

#2\.测试一下输入的内容是否正确
date_d=$(echo ${date2} | grep '[0-9]\{8\}')
if [ "${date_d}" == ""]; then
	echo "You input the wrong date format...."
	exit 1
fi

#3\.开始计算日期
declare -i date_dem=$(date --date="${date2}" +%s)#退伍日期秒数
declare -i date_now=$(date +%s)#现在日期秒数
declare -i date_total_s=$((${date_dem}-${date_now}))#剩余秒数统计
declare -i date_d=$(($date_total_s/60/60/24))#转为日数
if [ "${date_d}" < "0" ]; then
	echo "You had been demobilization before: $((-1*${date_d})) ago"
else
	declare -i date_h=$(($((${date_total_s}-${date_d}*60*60*24))/60/60))
	echo "You will demobilize after ${date_d} days and ${date_h} hours."

利用case…esac判断
case $变量名称 in
“第一个变量内容”)
程序段
;;
“第二个变量内容”)
程序段
;;
*)#*代表所有其他值
不包含第一个和第二个变量内容的其他程序执行段
exit 1
;;
esac

一般来说,使用case $变量 in 这个语法时,当中的那个变量有两种取得的方式:
直接下达式:这个就是在命令中作为参数传进去
互动式:通过read这个指令来让使用者输入变量的内容

来一个例子

#让使用者能够输入 one, two, three , 并且将使用者的变量显示到屏幕上,如果不是 one, two, three 时,就告知使用者仅 有这三种选择
vim show123.sh
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH

echo "This program will input your selection!"
read -p "Input your choice:" choice
case ${choice} in
	"one")
		echo "Your choice is ONE"
		;;
	 "two")
	 	echo "Your choice is TWO"
	 	;;
	 "three")
	 	echo "Your choice is THREE"
	 	;;
	 *)
	 	echo "Usage ${0} {one|two|three}"
	 	;;
esac

上面是自己输入参数,也可以在下命令的时候输入参数,case后面改成${1}就可以了

利用function功能
function fname(){
程序段
}
要注意的是,因为shell script的执行方式是由上而下,由左而右,因此里面函数的设置一定要在程序的最前面

#将上面改一下,加一个函数
vim show123-2.sh

#!/bin/bash
PATH=/bin:/sbin:/usr/bin:usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH

function printit(){
	echo -n "Your choice is "#加上-n可以不断行继续在同一行显示
}

echo "This program will input your selection!"
#read -p "Input your choice:" choice
case ${1} in
	"one")
		**printit**; echo ${1} | tr 'a-z' 'A-Z'
		;;
	 "two")
	 	**printit**; echo ${1} | tr 'a-z' 'A-Z'
	 	;;
	 "three")
	 	**printit**; echo ${1} | tr 'a-z' 'A-Z'
	 	;;
	 *)
	 	echo "Usage ${0} {one|two|three}"
	 	;;
esac

function也是拥有内置变量的,他的内置变量与shell script类似,函数名称为$0,后续接的变量为$1,$2,…,两者并不等同,要注意不能搞混了,再次改写一下上面的例子

vim show123-3.sh
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH

function printit(){
	echo -n "Your choice is ${1}"#加上-n可以不断行继续在同一行显示
}

echo "This program will input your selection!"
#read -p "Input your choice:" choice
case ${1} in
	"one")
		**printit 1**;
		;;
	 "two")
	 	**printit 2**
	 	;;
	 "three")
	 	**printit 3**
	 	;;
	 *)
	 	echo "Usage ${0} {one|two|three}"
	 	;;
esac

#调用上面的脚本
sh show123-3.sh one#此时出现的结果就是1了

循环

while do done, until do done(不定循环)
#满足条件就一直循环
while [condition]
do
程序段落
done
#满足条件就终止循环
until [condition]
do
程序段落
done

一个小练习:使用者输入yes或者是YES才结束程序的执行,否则就一直告知使用者输入字串

#用while

vim yes_to_stop.sh

#!/bin/bash
PATH=/bin:/sbin:/usr/bin:usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH

while [ "${yn}" != "yes" -a "${yn}" != "YES"]
do
	read -p "Please input YES/yes to stop this program: " yn
done
echo "OK! You input the correct answer."

#用until

vim yes_to_stop-2.sh

#!/bin/bash
PATH=/bin:/sbin:/usr/bin:usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH

until [ "${yn}" == "yes" -a "${yn}" == "YES"]
do
	read -p "Please input YES/yes to stop this program: " yn
done
echo "OK! You input the correct answer."

再来一个小例子:计算1+2+3+…+100

vim cal_1_100.sh
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH

i=0
sum=0
while i<=100
do
	i=$((${i}+1))
	sum=$((${sum}+${i}))
done
echo "The result of '1+2+3+...+100' is ${sum}"

#执行一下上面这个脚本
sh cal_1_100.sh

for…do…done(固定循环)
for var in con1 con2 con3 …
do
程序段
done

以上面的例子来说,这个 $var 的变量内容在循环工作时:
1、 第一次循环时, $var 的内容为 con1 ;
2、 第二次循环时, $var 的内容为 con2 ;
3、 第三次循环时, $var 的内容为 con3 ;

然后做个小练习

vim show_animal.sh
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH

for animal in dog cat element
do
	echo "There are ${animal}s...."
#用id检查使用者的信息
vim userid.sh
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
users=$(cut -d ":" -f 1 /etc/passwd)
for username in ${users}
do 
	id ${username}
done

一连串的数字循环的情况

vim pingip.sh
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH

network="192.168.1"
for sitenu in $(seq 1 100)
do
	#取得ping的回传值是正确的还是失败的
	ping -c 1 -w 1 ${network}.${sitenu} &> /dev/null && result=0 || result=1
	#开始显示结果是正确的启动还是错误的没有连通
	if [ "${result}" == "0" ]; then
		echo "Server ${network}.${sitenu} is UP."
	else
		echo "Server ${network}.${sitenu} is DOWN"
	fi
done

上面 ( s e q 1100 ) 表 示 连 续 出 现 的 意 思 , 此 外 , 也 可 以 使 用 1..100 来 取 代 (seq 1 100)表示连续出现的意思,此外,也可以使用{1..100}来取代 (seq1100)使1..100(seq 1 100),中间两个小点表示连续出现,{a…g}就表示从a到g的所有字母

再来一个例子:让使用者输入某个目录文件名。然后找出某目录内的文件名的权限。

vim dir_perm.sh
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH

#1先看看这个目录是否存在
read -p "Please input a directory: " dir
if [ "${dir}" == "" -o ! -d "${dir}" ]; then
	echo "The ${dir} is NOT exist in your system"
	exit 1
fi

#2测试文件
filelist=$(ls ${dir})#列出该目录下的文件名称
for filename in ${filelist}
do
	perm=""
	test -r "${dir}/${filename}" && perm="${perm} readable"
	test -w "${dir}/${filename}" && perm="${perm} writable"
	test -x "${dir}/${filename}" && perm="${perm} executable"
	echo "The file ${dir}/${filename}'s permission is ${perm}"
done

for…do…done的数值处理
除了上述的方法外,for循环还有另外一种写法
for ((初始值;限制值;执行步阶))
do
程序段
done

#从1加到用户输入的数
vim cal_1_100-2.sh
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH

read -p "Please input a number, I will count for 1+2+...+your_input: " nu

s=0
for ((i=0; i<=nu; i=i+1))
do
	s=$(${s}+${i})
done
echo "The result of '1+2+3+...+${nu}' is ${s}"

搭配乱数与阵列的实验

vim what_to_eat.sh
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH

eat[1]="haha"
eat[2]='heihei'
eat[3]='houhou'
eat[4]='xixi'
eat[5]='wawa'
eatnum=5

check=$((${RANDOM}*${eatnum}/32767 + 1))
echo "your may eat ${eat[${check}]}"

上面每次出来一个店家,如果想要每次出来3个呢

vim what_to_eat-2.sh
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH

eat[1]="haha"
eat[2]='heihei'
eat[3]='houhou'
eat[4]='xixi'
eat[5]='wawa'
eatnum=5

eated=0
while [ "${eated}" < "3" ]
do
	check=$((${RANDOM}*${eatnum}/32767 + 1))
	mycheck=0
	if [ "${eated}" >= 1]; then
		for i in $(seq 1 ${eated})
		do
			if [ "${eatedcon[$i]}" == $check ]; then
				mycheck=1
			fi
		done
	fi
	if [ ${mycheck} == 0 ]; then
		echo "your may eat ${eat[${check}]}"
		eated=$((${eated}+1))
		eatedcon[${eated}]=${check}
	fi
done


echo "your may eat ${eat[${check}]}"

shell script的追踪与debug

sh [-nvx] scripts.sh
选项与参数:
-n :不要执行 script,仅查询语法的问题;
-v :再执行 sccript 前,先将 scripts 的内容输出到屏幕上;
-x :将使用到的 script 内容显示到屏幕上,这是很有用的参数!

#范例1:测试dir_perm.sh有无语法问题
sh -n dir_perm.sh#若语法没有问题不会显示任何信息
#范例2:将show_animal.sh的执行过程全部列出来
sh -x show_animal.sh
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值