Shell学习基础之变量、字符串、数组、符号

一、关于Shell

1、Shell是什么

Shell 是一个用 C 语言编写的程序,它是用户使用 Linux 的桥梁,Shell 既是一种命令语言,又是一种程序设计语言,可以简单的理解为将各种Linux命令写入到执行文件中。

Shell 是指一种应用程序,这个应用程序提供了一个界面,用户通过这个界面访问操作系统内核的服务。

Shell在线编辑器


2、为什么要学习Shell

Shell属于内置的脚本,程序开发的效率非常高,依赖于功能强大的命令可以迅速地完成开发任务(批处理)语法简单,代码写起来比较轻松,简单易学,项目中常通过shell脚本启动/停止程序,做一些定时任务等(如定时备份数据,定时清理日志文件)


3、Shell的第一个Hello World

#!/bin/bash
echo "Hello World !"

#! 是一个约定的标记,它告诉系统这个脚本需要什么解释器来执行,表示使用哪一种 Shell。#!bin/sh   Bourne shell版本;#!bin/bash Bourne Again Shell 版本

echo 命令用于向窗口输出文本

如果执行sh文件的时候提示'-bash: ./shell.sh: Permission denied',执行chmod +x ./sh文件名,使脚本具有执行权限


二、Shell 变量

1、变量命名规则

  • 命名只能使用英文字母,数字和下划线“_”,但不能以数字开头
  • 等号左右两侧不能有空格,变量的值如果有空格,需要使用单引号或双引号包括,如str='hello word'
[root@i-eikjpmcq data]# cat shell.sh 
#!/bin/bash
# = 前后有空格,值有空格会报错
str = hello word
echo ${str}
[root@i-eikjpmcq data]# sh shell.sh 
shell.sh: line 2: str: command not found
[root@i-eikjpmcq data]# 



[root@i-eikjpmcq data]# cat shell.sh 
#!/bin/bash
#=前后不要有空格,值如果有空格,用单引号或双引号包起来
str='hello word'
echo ${str}
[root@i-eikjpmcq data]# sh shell.sh 
hello word
[root@i-eikjpmcq data]# 
  • 不能使用bash里的关键字做变量名(可用help命令查看保留关键字)
  • 环境变量建议大写,便于区分

2、使用变量

在变量名前面加‘$’,如$变量名或者${变量名},符号'{}'是可选的,加不加都行,加花括号是为了帮助解释器识别变量的边界,推荐给所有变量加上花括号,这是个好的编程习惯

[root@i-eikjpmcq data]# cat shell.sh 
#!/bin/bash
str='hello'
echo $str
#{}为可选项,推荐加上
echo ${str}

[root@i-eikjpmcq data]# sh shell.sh 
hello
hello
[root@i-eikjpmcq data]# 



[root@i-eikjpmcq data]# cat shell.sh 
#!/bin/bash
str='hello'
#如果不加{},解析器会把strTOM当成一个变量名,但实际上并没有这个变量,输出为空
echo "$strTOM"

[root@i-eikjpmcq data]# sh shell.sh 

[root@i-eikjpmcq data]# 

已定义的变量,可以被重新定义,注意,第二次赋值的时候不能写$str= " word " , 使用变量的时候才加$

[root@i-eikjpmcq data]# cat shell.sh 
#!/bin/bash
str='hello'
echo ${str}

str='word'
echo ${str}

#再次复制的时候不要使用$
${str}='csdn'
echo ${str}

[root@i-eikjpmcq data]# sh shell.sh 
hello
word
shell.sh: line 8: word=csdn: command not found
word
[root@i-eikjpmcq data]# 

3、只读变量

使用 readonly 命令可以将变量定义为只读变量,只读变量的值不能被改变

[root@i-eikjpmcq data]# cat shell.sh 
#!/bin/bash
str='hello'
readonly str
echo ${str}

#str使用reabonly关键字设置为只读,再次赋值会报错
str='word'
echo ${str}

[root@i-eikjpmcq data]# sh shell.sh 
hello
shell.sh: line 7: str: readonly variable
[root@i-eikjpmcq data]# 

4、删除变量

使用 unset 命令可以删除变量,变量被删除后不能再次使用,unset 命令不能删除只读变量

[root@i-eikjpmcq data]# cat shell.sh 
#!/bin/bash
str1='CSDN'
unset str1

#str1已经使用unset进行删除,输出为空
echo ${str1}


str2='hello'
readonly str2
#str2使用reabonly关键字设置为只读,不能删除
unset str2
echo ${str2}

[root@i-eikjpmcq data]# sh shell.sh 

shell.sh: line 12: unset: str2: cannot unset: readonly variable
hello
[root@i-eikjpmcq data]# 

5、变量类型

  • 用户自定义变量: 最常见的变量,由用户自由定义变量名和变量的值。

  • 环境变量(/etc/profile): 所有的程序,包括shell启动的程序,都能访问环境变量,有些程序需要环境变量来保证其正常运行。必要的时候shell脚本也可以定义环境变量。

#使用export声明的变量即是环境变量
export age="18"

#删除环境变量gender
unset gender  

#env命令和set命令的区别:
#set命令可以查看所有变量,而env命令只能查看环境变量。
[root@i-eikjpmcq ~]# env
XDG_SESSION_ID=6763
HOSTNAME=i-eikjpmcq
TERM=xterm
SHELL=/bin/bash
HISTSIZE=1000
SSH_CLIENT=192.168.4.220 51138 22
SSH_TTY=/dev/pts/1
USER=root
[root@i-eikjpmcq ~]# 
  • 位置参数变量: 这种变量主要是用来向脚本当中传递参数或数据的,变量名不能自定义,变量作用是固定的。

位置参数变量作用
$nn为数字,$0表示当前Shell脚本程序的名称,$1-9代表第一到第九个参数,十以上的参数需要用大括号包含,如{10}
$*这个变量代表命令行中所有的参数,$把所有的参数看成一个整体
$@这个变量也代表命令行中所有的参数,不过$@把每个参数区分对待
$#这个变量代表命令行中所有参数的个数
  • 预定义变量: 是Bash中已经定义好的变量,变量名不能自定义,变量作用也是固定的

预定义变量作用
$?最后一次执行的命令的返回状态。如果这个变量的值为0,证明上一个命令正确执行;如果这个变量的值为非О(具体是哪个数,由命令自己来决定),则证明上一个命令执行不正确了。
$$当前进程的进程号(PID)
$!后台运行的最后一个进程的进程号(PID)

三、Shell字符串

字符串是shell编程中最常用最有用的数据类型,字符串可以用单引号,也可以用双引号,也可以不用引号,单引号和双引号一般是为了解决字符串值中的空格

1、单引号

  • 单引号里的任何字符都会原样输出,单引号字符串中的变量是无效的;
[root@i-eikjpmcq data]# cat shell.sh 
#!/bin/bash
str1='我是单引号中的值 哈哈'
echo ${str1}

#单引号包含的读取变量无效,会原样输出,但是双引号会正确输出变量值
echo '${str1}'

[root@i-eikjpmcq data]# sh shell.sh 
我是单引号中的值 哈哈
${str1}
[root@i-eikjpmcq data]# 
  • 单引号字串中不能出现单独一个的单引号(对单引号使用转义符后也不行),但可成对出现,作为字符串拼接使用。
[root@i-eikjpmcq data]# cat shell.sh 
#!/bin/bash
#单引号不能单独(不成对)出现,即使使用\转义也不行
str1='我是\'单引号中的值 哈哈'
echo ${str1}
[root@i-eikjpmcq data]# sh shell.sh 
shell.sh: line 2: unexpected EOF while looking for matching `''
shell.sh: line 4: syntax error: unexpected end of file
[root@i-eikjpmcq data]# 



#单引号拼接变量
[root@i-eikjpmcq data]# cat shell.sh 
#!/bin/bash
str1='马云'
echo 'hello,'${str1}'!'

[root@i-eikjpmcq data]# sh shell.sh 
hello,马云!
[root@i-eikjpmcq data]# 

2、双引号

  • 双引号里可以有变量,可以拼接字符串
[root@i-eikjpmcq data]# cat shell.sh 
#!/bin/bash
str1="我是双引号引号中的值 哈哈"
echo "hello word ${str1}"

[root@i-eikjpmcq data]# sh shell.sh 
hello word 我是双引号引号中的值 哈哈
[root@i-eikjpmcq data]# 
[root@i-eikjpmcq data]# cat shell.sh 
#!/bin/bash
str1='马云'
#双引号拼接变量
echo "hello,"${str1}"!"
echo "hello,${str1}!"

[root@i-eikjpmcq data]# sh shell.sh 
hello,马云!
hello,马云!
[root@i-eikjpmcq data]# 
  • 双引号里可以出现转义字符
[root@i-eikjpmcq data]# cat shell.sh 
#!/bin/bash
str1="我是\"双引号中的值 哈哈"
echo ${str1}
[root@i-eikjpmcq data]# sh shell.sh 
我是"双引号中的值 哈哈
[root@i-eikjpmcq data]# 

3、获取字符串长度

${#变量名}

[root@i-eikjpmcq data]# cat shell.sh 
#!/bin/bash
str1="阿里巴巴是马云的"
echo "str1的变量值长度是:${#str1}"

[root@i-eikjpmcq data]# sh shell.sh 
str1的变量值长度是:8
[root@i-eikjpmcq data]# 

4、提取子字符串

${变量名:startIndex:endIndex}

[root@i-eikjpmcq data]# cat shell.sh 
#!/bin/bash
str1="阿里巴巴是马云的"
result=${str1:0:4}
#注意:第一个字符的索引值为 0
echo "获取str1变量值的0-4个字符:${result}"

[root@i-eikjpmcq data]# sh shell.sh 
获取str1变量值的0-4个字符:阿里巴巴
[root@i-eikjpmcq data]# 

四、Shell数组

bash支持一维数组(不支持多维数组),并且没有限定数组的大小,数组元素的下标由 0 开始编号。获取数组中的元素要利用下标,下标可以是整数或算术表达式,其值应大于或等于 0

1、定义数组

数组名=(value1 value2 ... valuen)

第一种:
names=(张三 李四 王五 二狗)
 
第二种:
names=(
张三 
李四 
王五 
二狗
)

第三种:可以不使用连续的下标,而且下标的范围没有限制
names[0]=张三 
names[1]=李四 
names[6]=王五 
......
names[n]=valuen

2、读取数组

${数组名[index]}  注:index为@ 表示获取数组的所有值

[root@i-eikjpmcq data]# cat shell.sh 
#!/bin/bash
names=(张三 李四 王五 二狗)
echo "获取数组names下标为2的值:${names[2]}"
[root@i-eikjpmcq data]# sh shell.sh 
获取数组names下标为2的值:王五
[root@i-eikjpmcq data]# 


#${数组名[@]}获取数组的所有元素
[root@i-eikjpmcq data]# cat shell.sh 
#!/bin/bash
names=(张三 李四 王五 二狗)
echo "获取数组names的所有值:${names[@]}"

[root@i-eikjpmcq data]# sh shell.sh 
获取数组names的所有值:张三 李四 王五 二狗
[root@i-eikjpmcq data]# 

3、获取数组的长度

${#数组名[@]}、${#数组名[*]}、${#数组名[index]}

[root@i-eikjpmcq data]# cat shell.sh 
#!/bin/bash
names=(张三 李四 王五 二狗)

#使用${#数组名[@]}获取数组长度
echo "使用@获取数组的长度:${#names[@]}"

#使用${数组名[*]}获取数组的长度
echo "使用*获取数组长度:${#names[*]}"


#使用${#数组名[n]}获取单个元素的长度
echo "使用下标获取单个元素的长度:${#names[0]}"

[root@i-eikjpmcq data]# sh shell.sh 
使用@获取数组的长度:4
使用*获取数组长度:4
使用下标获取单个元素的长度:2
[root@i-eikjpmcq data]# 

五、Shell中的运算符和特殊符号

一、运算符

  • 算数运算符

Shell 和其它编程语言不同,Shell 不能直接进行算数运算,必须使用数学计算命令,如下:

[root@i-eikjpmcq data]# cat shell.sh 
#!/bin/bash
sum=6+5
echo ${sum}

[root@i-eikjpmcq data]# sh shell.sh 
6+5
[root@i-eikjpmcq data]# 

可以看出并不是打印的11而是打印的6+5,Shell 不会直接进行算术运算,而是把+两边的数据(数值或者变量)当做字符串,把+当做字符串连接符,最终的结果是把两个字符串拼接在一起形成一个新的字符串。
这是因为,在 Bash Shell 中,如果不特别指明,每一个变量的值都是字符串,无论你给变量赋值时有没有使用引号,值都会以字符串的形式存储。
换句话说,Bash shell 在默认情况下不会区分变量类型,即使你将整数和小数赋值给变量,它们也会被视为字符串,这一点和大部分的编程语言不同。

因此shell的算术运算中有以下几种方法

名称语法范例备注
算术扩展变量=$((算术表达式))r=$((1+2*3))(())只支持整数的运算,小数运算会报错
使用外部程序expr变量=`expr 算术表达式`r=`expr 1 + 2`用expr表示后面的表达式为一个数学运算。需要注意的是,`并不是一个单引号,而是反引号(“Tab”键上面的那个符号),表达式和运算符之间要有空格,例如 2+2 是不对的,必须写成 2 + 2。r=`expr 4 * 5` #错误,乘法 r=`expr 4 \* 5`
使用[ ]变量=$[算术表达式] r=$[1+2] 
使用内置命令declaredeclare -i 变量=算术表达式declare -i r=1+2*3 
使用内置命令letlet 算术表达式let r=1+2

用let表示后面的表达式为一个数学运算。表达式中的变量前不必有$.如果表达式中包含了空格或其他特殊字符,则必须引起来。

例:let “I = I + 1” 或 let i=i+1

用let表示后面的表达式为一个数学运算。表达式中的变量前不必有$.如果表达式中包含了空格或其他特殊字符,则必须引起来。例:let “I = I + 1” 或 let i=i+1

运算符说明举例
+加法

$((num1+num2))

-减法$((num1-num2))
*乘法`expr $num1 \* $num2`
/除法$((num1%num2))
%取余$((num1/num2))
=赋值num1=${num3} 将把变量 num3 的值赋给 num1。
==

相等

[ $num1 == $num1 ] 用于比较两个字符串,相同则返回 true,不相同返回false
!=

不相等

[ $num1 != $num2 ] 用于比较两个字符串,不相同则返回 true,相同返回false

 

[root@i-eikjpmcq data]# cat shell.sh 
#!/bin/bash
num1=20
num2=10
# +
echo "num1+num2:$((num1+num2))"

# -
echo "num1-num2:$((num1-num2))"

# * 乘法符号需要转义
echo 'num1*num2=' `expr $num1 \* $num2`

# %
echo "num1%num2:$((num1%num2))"

# /
echo "num1/num2:$((num1/num2))"

#赋值 =
num3=40
num1=${num3}
echo "将num3的值${num3}赋值给num1,num1赋值后的值为:${num1}"

# == 判断相等
str1="a"
str2="a"
if [ $str1 == $str2 ]
then
	echo 'str1等于str2'
else
	echo 'str1不等于str2'
fi

# != 判断不等
if [ $a != $b ]
then
	echo 'a不等于b'
else
	echo 'a等于b'
fi

[root@i-eikjpmcq data]# sh shell.sh 
num1+num2:30
num1-num2:10
num1*num2= 200
num1%num2:0
num1/num2:2
将num3的值40赋值给num1,num1赋值后的值为:40
str1等于str2
a不等于b
[root@i-eikjpmcq data]# 

  • 关系运算符

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

关系运算符示例
等于

-eq:用于整数的比较

==:用于字符串、整数的比较

[ $num1 -eq $num1 ]、[ $str1 == $str1 ] ,相同则返回 true,不相同返回false
不等于

-ne:用于整数的比较

!=:用于字符串、整数的比较

[ $num1 -ne $num1 ]、[ $num1 != $num1 ],不相同则返回 true,相同返回false
大于-gt[ $num1 -gt $num2 ]左边的数是否大于右边的数,如果是返回 true。不是返回false
小于-lt[ $num1 -gt $num2 ]左边的数是否小于右边的数,如果是返回 true。不是返回false
大于等于-ge[ $num1 -ge $num2 ]左边的数是否大于等于右边的数,如果是返回 true。不是返回false
小于等于-le[ $num1 -le $num2 ]左边的数是否小于等于右边的数,如果是返回 true。不是返回false

 

[root@i-eikjpmcq data]# cat shell.sh 
#!/bin/bash
# eq比较数字
num1=20
num2=18
if [ $num1 -eq $num2 ]
then
         echo '是否-eq:true'
else
          echo '是否-eq:false'
fi

# == 比较字符串、数字
str1=a
str2=a
if [ $str1 == $str2 ]
then
         echo '是否==:true'
else
          echo '是否==:false'
fi 

# -gt 大于
if [ $num1 -gt $num2 ]
then
         echo '是否-gt:true'
else
          echo '是否-gt:false'
fi 


# -lt 小于
if [ $num1 -lt $num2 ]
then
         echo '是否-lt:true'
else
          echo '是否-lt:false'
fi 


# -ge 大于等于
num1=50
num2=30
if [ $num1 -ge $num2 ]
then
         echo '是否-ge:true'
else
          echo '是否-ge:false'
fi 


# -le 小于等于
num1=50
num2=30
if [ $num2 -le $num1 ]
then
         echo '是否-le:true'
else
          echo '是否-le:false'
fi 

[root@i-eikjpmcq data]# sh shell.sh 
是否-eq:false
是否==:true
是否-gt:true
是否-lt:false
是否-ge:true
是否-le:true
[root@i-eikjpmcq data]# 

  • 逻辑运算符

运算符说明举例
!非运算,表达式为 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。一个为假即为假,全部为真才是真
[root@i-eikjpmcq data]# cat shell.sh 
#!/bin/bash
#! 取反
num1=20
num2=20
#num1和num2相等,加了!,表示结果取反,所以输出为false
if [ !$num1 -eq $num2 ]
then
         echo '是否等于:true'
else
          echo '是否等于:false'
fi


# -o 或者
num1=10
num2=30
if [ $num1 -gt 20 -o $num2 -gt 40 ]
then
         echo 'num1大于20或者num2大于40满足其中一个条件'
else
          echo 'num1大于20或者num2大于40两个条件都不满足'
fi


# -a 并且
num1=10
num2=30
if [ $num1 -gt 6 -a $num2 -gt 20 ]
then
         echo 'num1大于6并且num2大于20这两个条件都满足'
else
          echo 'num1大于6并且num2大于20两个条件没有同时满足'
fi



[root@i-prb7e83w data]# sh shell.sh 
是否等于:false
num1大于20或者num2大于40两个条件都不满足
num1大于6并且num2大于20这两个条件都满足

  • 字符串运算符

运算符说明举例
-z检测字符串长度是否为0,为0返回 true。[ -z $strName ] 返回 false。
-n检测字符串长度是否为0,不为0返回 true。[ -n $strName ] 返回 true。
strName检测字符串是否为空,不为空返回 true。[ $strName ] 返回 true。
[root@i-prb7e83w data]# cat shell.sh 
#!/bin/bash
str1=''
if [ -z $str1 ]
then
         echo '长度是否为0:true'
else
          echo '长度是否为0:false'
fi


str2='hello'
if [ -z $str2 ]
then
         echo '长度是否不为0:true'
else
          echo '长度是否不为0:false'
fi


if [ $str2 ]
then
         echo '是否不为空:true'
else
          echo '是否为空:false'
fi

[root@i-prb7e83w data]# sh shell.sh 
长度是否为0:true
长度是否不为0:false
是否不为空:true
[root@i-prb7e83w data]# 

  • 文件测试运算符

如果同时存在几个文件权限的判断,只要有一个部分符合,则认为是有权限的。(下图红色加粗的几个为常用命令)

操作符说明举例
-b file检测文件是否是块设备文件,如果是,则返回 true。[ -b $file ] 返回 false。
-c file检测文件是否是字符设备文件,如果是,则返回 true。[ -b $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。
[root@i-prb7e83w data]# cat shell.sh 
#!/bin/bash
file=/data/shell.sh

# -d 检测是否是目录
if [ -d $file ]
then
   echo "-d:$file是目录"
else
   echo "-d:$file不是目录"
fi

# -f 检测是否是普通文件
if [ -f $file ]
then
   echo "-f:$file是普通文件"
else
   echo "-f:$file不是普通文件"
fi

# -r 检测是否可读
if [ -r $file ]
then
   echo "-r:$file可读"
else
   echo "-r:$file不可读"
fi

# -w 检测是否可写
if [ -w $file ]
then
   echo "-w:$file可写"
else
   echo "-w:$file不可写"
fi

# -x 检测是否可执行
# 如果结果为不可执行,使用命令 chmod +x 文件名,文件就变为可执行了
if [ -x $file ]
then
   echo "-x:$file可执行"
else
   echo "-x:$file不可执行"
fi

# -s 检测文件是否为空
if [ -d $file ]
then
   echo "-d:$file为空"
else
   echo "-d:$file不为空"
fi

# -e 检测文件、文件夹是否存在
if [ -e $file ]
then
   echo "-e:$file存在"
else
   echo "-e:$file不存在"
fi

[root@i-prb7e83w data]# sh shell.sh 
-d:/data/shell.sh不是目录
-f:/data/shell.sh是普通文件
-r:/data/shell.sh可读
-w:/data/shell.sh可写
-x:/data/shell.sh可执行
-d:/data/shell.sh不为空
-e:/data/shell.sh存在

二、特殊运算符

符号作用
’ ’单引号。在单引号中所有的特殊符号,如“$”和”(反引号)都没有特殊含义。单引号括起来的都是普通字符,会原样输出
“ ”双引号。在双引号中特殊符号都没有特殊含义,但是“$”,"`"(esc键下面)和“\”是例外,拥有“调用变量的值”、“引用命令”和“转义符”的特殊含义。
· ·反引号。反引号括起来的内容是系统命令,在Bash中会先执行它。和 ()作用一样,不过推荐使用 (),因为反引号非常容易看错。
$()和反引号作用一样,用来引用系统命令。(推荐使用)
()用于一串命令执行时,()中的命令会在子Shell中运行
{}用于一串命令执行时,{ }中的命令会在当前Shell中执行。也可以用于变量变形与替换。
[ ]用于变量的测试。
#

1.在shell文件的行首,作为声明标记,#!/bin/bash;

2. 其他地方作为注释使用,在一行中,#后面的内容并不会被执行

3. 但是用单/双引号包围时,#作为#号字符本身,不具有注释作用。

$用于调用变量的值,如需要调用变量name的值时,需要用$name的方式得到变量的值。
\转义符,跟在\之后的特殊符号将失去特殊含义,变为普通字符。如$将输出“$”符号,而不当做是变量引用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值