认识与学习Bash

只要能操作应用程序的接口都可称为shell。可以是图形接口,也可以是文字接口。

操作系统合法的shell均写在 /etc/shells 文件中。

用户默认登录取得的shell记录于 /etc/passwd 的最后一个字段。

bash进系统欢迎信息

直接登录系统:/etc/issue

远程登录系统:/etc/issue.net

全部设定登录:/etc/motd

issue中各字符含义

代码意义
\d显示本地时间的日期
\l显示第几个终端接口
\m显示硬件的等级(i386/i486/i586/i786...)
\n显示主机的网络名称
\O显示域名domain name
\r显示操作系统版本;同 uname -r
\t显示本地时间的时间
\S显示操作系统名称
\v显示操作系统版本

bash环境配置文件

login shell:获取bash时需要完整登入流程的,比如从tty1~6登入系统输入账号密码,就为 login shell

non-login shell:无需重复登入流程的,比如在系统内部启动tty1~6,不用输入账号密码,就为 non-login shell

login shell读取文件顺序:

一:首先一定会读取的   /etc/profile(整体环境配置)

二:接着读取使用者个人配置文件    【1】~/.bash_profile 【2】 ~/.bash_login【3】 ~/.profile   login shell只会读取三个文件中一个,读取顺序依次,若有一个存在,则后续的不再读取。

non-login shell仅读取 ~/.bashrc

历史命令-history

默认的命令记录条数可以到达1000个。记录存在于家目录的 .bash_history ,此文件记录的是前一次登录所执行过的命令,此次登录所执行的命令都被缓存在内存中,当成功注销系统后,此次命令才会记录到 ./bash_history 中

history [参数] historyfiles

n:数字,列出多少行

-c:将目前shell中所有的history内容全部消除

-a:将目前新增的history指令增入historyfiles中,若没写historyfiles,则默认写入 ~/.bash_history

-r:将history文件内容读到整个shell中的history记忆中

-w:将目前history记忆内容写入historyfiles中

同一账号同时多次登录时,最后一个注销的bash是最后写入的数据;

可与以下命令搭配使用

!number:执行第几个命令

!command:由最近的命令向前搜寻以command开头的命令并执行该命令

!!:执行上一个命令

[root@wzy ~]#who am i
root     pts/0        2023-04-25 03:04 (192.168.29.1)
[root@wzy ~]#echo zhangsan
zhangsan
[root@wzy ~]#echo lisi
lisi
[root@wzy ~]#history
822  who am i
823  echo zhangsan

824  echo lisi
825  history
[root@wzy ~]#!823
echo zhangsan
zhangsan
[root@wzy ~]#!!
echo zhangsan
zhangsan

[root@wzy ~]#!who
who am i
root     pts/0        2023-04-25 03:04 (192.168.29.1)

命令与文件补全-【Tab】键

【Tab】接在一串命令的第一个字后面,则为命令补全。

【Tab】接在一串命令的第二个字后面,则为文件补齐。

命令别名设置功能-alias

alias 新命令 = ‘旧命令 选项’

比如:alias lm = ‘ls -la’

取消alias 使用 unalias 新命令,比如 unalias lm

type:查询命令是否为bash shell 内置命令

type [-tpa] name

不加任何选项和参数时,会显示name是外部指令还是bash内建指令

-t:将name以不同的关键字代表其类别。file为外部指令;alias为别名;builtin为bash内建指令

-p:当name为外部指令时,显示完整文件名

-a:由PATH变量定义的路径中,将所有含name的指令都列出来,包括alias

内部命令:使用 type 命令时,如果返回结果为 "是别名"(aliased to)或 "是内置命令"(is a shell builtin),则该命令是内部命令。

外部命令:如果 type 命令返回命令的路径,如 "是哈希"(hashed)或直接显示命令的完整路径,那么该命令是外部命令。

PS1:提示字符的的设定

  • \d:可显示【星期 月 日】的日期格式
  • \H:完整的主机名
  • \h:仅去主机名在第一个小数点之前的名字
  • \t:显示时间,24小时格式的【HH:MM:SS】
  • \T:显示时间,12小时格式的【HH:MM:SS】
  • \A:显示时间,24小时格式的【HH:MM】
  • \@:显示时间,12小时格式的【am/pm】
  • \u:目前使用者的账号名
  • \v:bash的版本信息
  • \w:完整的工作目录名称,由根目录写起,但家目录会以 ~ 代替
  • \W:利用 basename 函数取得工作目录名称,所以仅列出最后一个目录名
  • \#:下达的第几个指令
  • \$:提示字符,root显示 # ,否则显示 $

$:当前shell的线程代号

echo $$ 出现的数字即当前PID号码

locale

/etc/locale.conf 影响显示结果的语系变量;

其中最重要的两个变量 LANG 或 LC_ALL ,这两个设定后其他语系变量会被这两个替代。

read:读取键盘输入

read [-pt] 变量

-p:后面接提示的用户的字符

-t:后面接等待的秒数,时间到后结束等待。

#提示用户5秒内输入名字,用变量 name 接收

[root@wzy ~]#read -p "5秒内输出名字:" -t 5 name
5秒内输出名字:haha
[root@wzy ~]#echo $name
haha

路径与命令搜寻顺序 

输入ls命令,命令搜寻顺序为

  1. 以相对/绝对路径执行命令,例如 /bin/ls 或 ./ls
  2. 由alias找到该命令来执行
  3. 由bash内建builtin命令来执行
  4. 通过$PATH变量的顺序搜寻的第一个命令来执行

变量

变量表示命名的内存空间将数据放在内存空间中,通过变量名引用,获取数据

根据范围划分

普通变量:生效范围为当前shell进程

环境变量:生效范围为当前shell进程及其子进程

本地变量:生效范围为当前shell进程中某代码片段,通常是函数

赋值

  • 直接字符串:name='root'
  • 变量引用:name="$USER"
  • 命令引用:name=`COMMAND`

变量赋值是临时生效,当退出终端后,变量自动删除,无法持久保存,脚本中的变量会随着脚本结束而自动删除

引用

$name 或 ${name};建议 ${变量名}

变量设定规则:

  • 变量与变量内容以一个等号 = 来连接
  • 等号两边不能直接接空格符
  • 变量名称只能是英文字母、数字和下划线,但开头字符不能是数字
  • 不能使用系统中关键字,如if、for、USER等
  • 变量内容若有空格符可用双引号或单引号将变量内容括住;但是 双引号 内字符可保持原有特性单引号 内字符全部视为纯文本
  • 可用跳脱字符反斜杠 \ 将特殊符号(【enter】/【空格】/$/’ )等变成纯文本
  • 一串指令借用其他额外指令提供的信息时,可用反单引号 `指令` 或 $(指令)
  • 若该变量为扩增变量内容时,可用 “$变量名称” 或 ${变量} 累加内容
  • 若该变量需在其他子程序执行,则要以 export 变量  来使变量成环境变量
  • 通常大写字符为系统默认变量,自行设定的变量可以用小写字符
  • 大驼峰StudentFirstName,小驼峰studentFirstName,下划线student_name
  • 见名知义,用英文单词命名并体现实际作用

取消变量

unset 变量

变量数据类型

  • 字符   变量类型默认为字符串;
  • 数值:整型   bash 环境中的数值运算,预设仅能达到整数形态,如1/3为0;

位置变量

命令:.      /test.sh opt1 opt2 opt3 opt4

位置变量:   $0        $1    $2    $3    $4

$1、$2等对应第一个、第二个参数。

shift 数字:移动位置变量变量,后面不加数字,默认为1。

[root@centos8 data]# cat shift.sh
#!/bin/bash
echo "first=$1   second=$2   third=$3"
shift
echo "first=$1   second=$2   third=$3"

[root@centos8 data]# bash shift.sh 1 2 3
first=1   second=2   third=3
first=2   second=3   third=

$0:命令本身,包括路径

$#:代表除了$0以外,后面接的参数个数,如上即 $# 为4

$@:代表除了$0以外,所有的参数,如上即 “opt1“ “opt2“ “opt3“ “opt4“,每个变量是独立的,每个变量都用双引号括起来

$*:代表除了$0以外,所有的参数,如上即 “opt1 opt2 opt3 opt4“,每个变量之间用空格分割,共用一个双引号

清空所有位置变量

set --

环境变量

env:查看环境变量

[root@wzy ~]#env
#颜色显示设定
LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=01;05;37;41:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.zst=01;31:*.tzst=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.wim=01;31:*.swm=01;31:*.dwm=01;31:*.esd=01;31:*.jpg=01;35:*.jpeg=01;35:*.mjpg=01;35:*.mjpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=01;36:*.au=01;36:*.flac=01;36:*.m4a=01;36:*.mid=01;36:*.midi=01;36:*.mka=01;36:*.mp3=01;36:*.mpc=01;36:*.ogg=01;36:*.ra=01;36:*.wav=01;36:*.oga=01;36:*.opus=01;36:*.spx=01;36:*.xspf=01;36:
#发起SSH连接的客户端IP、端口、服务端IP、端口
SSH_CONNECTION=192.168.29.1 14638 192.168.29.141 22
#语系设定
LANG=en_US.UTF-8
#对历史命令去重
HISTCONTROL=ignoredups
#设定将图形显示到何处
DISPLAY=localhost:10.0
#这部主机的主机名
HOSTNAME=wzy.localdomain
#
XDG_SESSION_ID=1
#使用者名称
USER=root
#当前用户所在的工作目录
PWD=/root
#当前用户家目录
HOME=/root
#发起SSH连接的客户端IP、端口、服务端端口
SSH_CLIENT=192.168.29.1 14638 22
#
XDG_DATA_DIRS=/root/.local/share/flatpak/exports/share:/var/lib/flatpak/exports/share:/usr/local/share:/usr/share
#SSH使用的终端
SSH_TTY=/dev/pts/0
#
MAIL=/var/spool/mail/root
#此终端使用的环境是哪种类型
TERM=xterm
#当前环境下使用的shell
SHELL=/bin/bash
#
SHLVL=1
#
LOGNAME=root
#
DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/0/bus
#
XDG_RUNTIME_DIR=/run/user/0
#环境变量,若有不想加路径执行的命令,把命令路径添加到PATH即可
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
#设定history记录的命令数
HISTSIZE=1000
#
LESSOPEN=||/usr/bin/lesspipe.sh %s
#上次使用的命令的最后一个参数或命令本身
_=/usr/bin/env

set:观察所有变量(含环境变量和自定义变量)

export:可使自定义变量转成环境变量

export 变量名称

环境变量可被子进程继续引用

查看指定进程的环境变量

cat /proc/$PID/environ

直接声明环境变量

export name=value 或 declare -x name=value

declare:可使环境变量转成自定义变量

declare +x 变量名称

自定义变量不会被子进程继续引用

declare [-aixr] 变量

-a:将变量类型设定为数组

-A:将变量类型设定为关联数组

-i:将变量类型设定为整数

-x:将变量设定为环境变量,+x 可将环境变量转为自定义变量

-r:将变量设定为 readonly 类型,该变量不可被更改内容,也不能unset

只读变量

只读变量,只能声明定义,后续无法修改删除,即常量

定义只读变量

readonly 变量名

declare -r 变量名

查看只读变量

readonly [-p]

declare -r

退出状态码变量

进程执行后使用 $? 保存状态码相关数字。

执行命令成功返回0;执行命令失败返回其他数字。范围0-255

注意
  • 脚本中一旦遇到exit命令,脚本会立即终止;终止退出状态取决于exit命令后面的数字
  • 如果exit后面无数字,终止退出状态取决于exit命令前面的执行结果
  • 如果没有exit命令,即未给脚本指定退出状态码,整个脚本的退出状态码取决于脚本中执行的最后一条命令的状态码

变量中字符串的处理

基于偏移量取字符串

返回字符串变量var的字符的长度,一个汉字算一个字符
${#var}

返回字符串变量var中从第offset个字符后(不包括第offset个字符)的字符开始,到最后的部分,offset的取值在0 到 ${#var}-1 之间(bash4.2后,允许为负值)
${var:offset}

返回字符串变量var中从第offset个字符后(不包括第offset个字符)的字符开始,长度为number的部分
${var:offset:number}

取字符串的最右侧几个字符,取字符串的最右侧几个字符, 注意:冒号后必须有一空白字符
${var: -length}

从最左侧跳过offset字符,一直向右取到距离最右侧lengh个字符之前的内容,即:掐头去尾
${var:offset:-length}

先从最右侧向左取到length个字符开始,再向右取到距离最右侧offset个字符之间的内容,注意:-length前空格,并且length必须大于offset
${var: -length:-offset}

[root@centos8 data]#name="abcdefghijklmn"
[root@centos8 data]#echo ${#name}
14
[root@centos8 data]#echo ${name:3}
defghijklmn
[root@centos8 data]#echo ${name:3:2}
de
[root@centos8 data]#echo ${name: -4}
klmn
[root@centos8 data]#echo ${name:4:-5}
efghi
[root@centos8 data]#echo ${name: -5:-3}
jk

基于模式取子串

word是指定的任意字符,自左而右,查找var变量所存储的字符串中:

懒惰模式,删除字符串开头至第一次出现word字符串(含)之间的所有字符,以第一个word为界删左留右
${var#*word}

贪婪模式,删除的是字符串开头至最后一次出现word字符之间的所有内容,以最后一个word为界删左留右

${var##*word}

[root@centos8 data]#file="var/log/message"
[root@centos8 data]#echo ${file#*/}
log/message
[root@centos8 data]#echo ${file##*/}
message

word是指定的任意字符,自右而左,查找var变量所存储的字符串中:
懒惰模式,删除字符串最后一个字符向左至第一次出现word字符串(含)之间的所有字符,即以从右向左的第一个word为界,删右留左
${var%word*}
 

贪婪模式,删除字符串最后一个字符向左至最后一次出现word字符之间的所有字符,以从右向左的最后一个word为界,删右留左
${var%%word*}
${var%%word}

[root@centos8 data]#url="http://wenzi.com:8080"
[root@centos8 data]#echo ${url%:*}
http://wenzi.com
[root@centos8 data]#echo ${url%%:*}
http

查找并替换

查找var所表示的字符串中,第一次被pattern所匹配到的字符串,以substr替换之,懒惰模式
${var/pattern/substr}

查找var所表示的字符串中,所有能被pattern所匹配到的字符串,以substr替换之,贪婪模式
${var//pattern/substr}

查找var所表示的字符串中,行首被pattern所匹配到的字符串,以substr替换之
${var/#pattern/substr}

查找var所表示的字符串中,行尾被pattern所匹配到的字符串,以substr替换之
${var/%pattern/substr}

查找并删除

删除var表示的字符串中第一次被pattern匹配到的字符串,懒惰模式
${var/pattern}

删除var表示的字符串中所有被pattern匹配到的字符串,贪婪模式
${var//pattern}

删除var表示的字符串中所有以pattern为行首匹配到的字符串
${var/#pattern}

删除var所表示的字符串中所有以pattern为行尾所匹配到的字符串
${var/%pattern}

字符大小写转换

把var中的所有小写字母转换为大写
${var^^}

把var中的所有大写字母转换为小写
${var,,}

变量拓展

扩展以所有prefix开头的变量
${!prefix*}
${!prefix@}

[root@centos8 data]#wz1=1;wz2=2;wz3=3
[root@centos8 data]#echo ${!wz*}
wz1 wz2 wz3

高级变量赋值

如下:var 和 str 为变量,针对 str 是否有设定来决定 var 的值。

  • [str:]代表 str 没有设定或为空的字符串
  • [str]代表没有该变量
变量设定方式str没有设定str为空字符串str已设定为非空字符串
var=${str-expr}var=exprvar=var=$str
var=${str:-expr}var=exprvar=exprvar=$str
var=${str+expr}var=var=exprvar=expr
var=${str:+expr}var=var=var=expr
var=${str=expr}

str=expr

var=expr

str不变

var=

str不变

var=$str

var=${str:=expr}

str=expr

var=expr

str=expr

var=expr

str不变

var=$str

var=${str?expr}expr输出至stderrvar=var=$str
var=${str:?expr}expr输出至stderrexpr输出至stderrvar=$str

array:数组

介绍

变量:存储单个元素的内存空间

数组:存储多个元素的连续的内存空间,相当于多个变量集合

数组名和索引

  • 索引的编号从0开始,属于数值索引
  • 索引可支持使用自定义的格式,而不仅是数值格式,即为关联索引,bash4.0版本后支持
  • bash的数组支持索引不连续

声明数组

普通数组可不事先声明,直接使用

declare -a array_name

关联数组必须事先声明,再使用

declare -A array_name

两者不可相互转换

赋值

  • 一次只赋值一个元素

array_name[index]=value

week[1]="one"

week[2]="two"

  • 一次赋值全部元素

array_name=("var1" "var2" ...)

name=("zhangsan" "lisi" "wangwu")

serial=({1..10})

alpha=({a..z})

file=(*.sh)

  • 只赋值特定元素

array_name=([0]="var1" [3]="var2" ...)

title=([0]="a" [3]="b" [9]="c")

引用

  • 显示所有数组

delcare -a

  • 引用特定数组元素

${array_name[index]}   如果省略[index]下标将引用下标为0的元素

[root@centos8 data]#declare -a title=([0]="a" [3]="b" [4]="c")

[root@centos8 data]#echo ${title[3]}
b

[root@centos8 data]#echo ${title}
a

  • 引用数组所有元素

${array_name[*]}

${array_name[@]}

[root@centos8 data]#declare -a title=([0]="a" [3]="b" [4]="c")

[root@centos8 data]#echo ${title[*]}
a b c
[root@centos8 data]#echo ${title[@]}
a b c

  • 数组长度或数组中元素个数

${#array_name[*]}

${#array_name[@]}

[root@centos8 data]#declare -a title=([0]="a" [3]="b" [4]="c")

[root@centos8 data]#echo ${#title[*]}
3
[root@centos8 data]#echo ${#title[@]}
3

  • 数组的所有下标

${!array_name[*]}

${!array_name[@]}

[root@centos8 data]#declare -a title=([0]="a" [3]="b" [4]="c")

[root@centos8 data]#echo ${!title[@]}
0 3 4
[root@centos8 data]#echo ${!title[*]}
0 3 4

删除

  • 删除数组中某个元素会使索引不连续

unset array_name[index]

[root@centos8 data]#declare -a title=([0]="a" [3]="b" [4]="c")

[root@centos8 data]#unset title[3]
[root@centos8 data]#echo ${title[@]}
a c

  • 删除整个数组

unset array_name

[root@centos8 data]#unset title

数组数据处理

${array_name[@]:offset:number}

${array_name[*]:offset:number}

  • offset指要跳过的元素个数
  • number指取出的元素个数

取出指定偏移量后(跳过几个)的所有元素

${array_name[@]:offset}

${array_name[*]:offset}

[root@centos8 data]#num=({1..10})
[root@centos8 data]#echo ${num[*]}
1 2 3 4 5 6 7 8 9 10

[root@centos8 data]#echo ${num[*]:2:4}
3 4 5 6

[root@centos8 data]#echo ${num[*]:3}
4 5 6 7 8 9 10

向数组中追加元素

array[${array[*]}]=value

array[${array[@]}]=value

[root@centos8 data]#num=({1..10})

[root@centos8 data]#num[${#num[@]}]=11

[root@centos8 data]#echo ${num[*]}
1 2 3 4 5 6 7 8 9 10 11

常用通配符

通配符常用于命令行或脚本等bash环境

*   匹配0个或无穷个任意字符

[root@wzy data]#touch abc.txt  ab.txt  a.txt
[root@wzy data]#ls a*.txt
abc.txt  ab.txt  a.txt
[root@wzy data]#ls a*
abc.txt  ab.txt  a.txt

?   匹配一个任意字符

[root@wzy data]#touch a.txt ab.txt abc.txt adc.txt
[root@wzy data]#ls a?c.txt
abc.txt  adc.txt
[root@wzy data]#ls a?.txt
ab.txt

[xxx]   匹配中括号内的任意一个字符;[0-9] 代表0到9之间所有数字

[root@wzy data]#touch a.txt ab.txt abc.txt abcd.txt abce.txt

[root@wzy data]#ls a[bcd].txt
ab.txt
[root@wzy data]#ls abc[de].txt
abcd.txt  abce.txt 

[-]   中括号内有减号,代表在编码顺序内的所有字符;[0-9] 代表0到9之间所有数字

[root@wzy data]#touch a{0..9}.txt;ls

a0.txt   a1.txt   a2.txt   a3.txt   a4.txt   a5.txt   a6.txt   a7.txt   a8.txt   a9.txt
[root@wzy data]#ls a[1-3].txt
a1.txt  a2.txt  a3.txt

[^]   中括号内有指数符号,代表反向;[^abc] 代表有一个非a或b或c的字符 

[root@wzy data]#ls a[^7-9].txt
a0.txt  a1.txt  a2.txt  a3.txt  a4.txt  a5.txt  a6.txt

常用特殊符号

通配符说明
;连续命令的分隔符
#注释符号,其后面的数据均不执行
\跳脱符号、转义符,将特殊符号或通配符转换为一般文本字符
~用户的家目录
-上次的工作目录
.当前工作目录
..上级目录
$使用变量前需要加的符号
&工作控制,将指令变成背景下工作
/目录符号,路径分割符
!

逻辑运算中的“非”

()小括号,在中间为子shell的起始与结束
{}花括号,在中间为命令区块的组合

 "":双引号,中间内容特殊符号、通配符或变量保持原有特性

[root@wzy data]#name=zhangsan
[root@wzy data]#echo "$name"
zhangsan

'':单引号,中间内容转变为纯文本

[root@wzy data]#echo '$name'
$name

``:反引号,中间内容优先执行

[root@wzy data]#echo date
date
[root@wzy data]#echo `date`
Sat Apr 15 11:02:11 CST 2023

标准输入、标准输出、标准错误输出 

标准输入stdin :代码0,使用 < 或 <<;< 将原本由键盘输入的内容由文件内容取代 ,<< 结束标志的输入字符

[root@wzy data]#vim name
zhangsan
lisi

[root@wzy data]#cat > newfile < name
[root@wzy data]#ll
total 8
-rw-r--r-- 1 root root 14 Apr 15 10:30 name
-rw-r--r-- 1 root root 14 Apr 15 10:31 newfile
[root@wzy data]#cat newfile 
zhangsan
lisi

标准输出stdout :代码1,使用 > 或 >>;> 代表覆盖,>> 代表追加

标准错误输出stderr:代码2,使用 2> 或 2>>

无论正确错误都指向一个位置:&>

#使用一般身份账号wenzi搜寻 /home 目录下是否有名为 .bashrc 的文件存在

[wenzi@wzy ~]$find /home -name .bashrc
/home/roo/.bashrc                                                  此行正常输出
/home/wenzi/.bashrc                                              此行正常输出
find: ‘/home/wenzi/encrypt’: Permission denied     此行是错误输出

#将上述stdout和stderr分别存储到不同的文件中

[wenzi@wzy ~]$find /home -name .bashrc > stdout.txt 2> stderr.txt
[wenzi@wzy ~]$cat stdout.txt 
/home/roo/.bashrc
/home/wenzi/.bashrc
[wenzi@wzy ~]$cat stderr.txt 
find: ‘/home/wenzi/encrypt’: Permission denied

#将错误的数据丢弃,屏幕只显示正确的数据

[wenzi@wzy ~]$find /home -name .bashrc 2>/dev/null 
/home/roo/.bashrc
/home/wenzi/.bashrc


#将指令的数据全部写入名为list.txt的文件中

[wenzi@wzy ~]$find /home -name .bashrc &>list.txt
[wenzi@wzy ~]$cat list.txt 
/home/roo/.bashrc
/home/wenzi/.bashrc
find: ‘/home/wenzi/encrypt’: Permission denied

高级用法

命令 <<< "字符串"

[root@centos8 ~]# seq -s + 10
1+2+3+4+5+6+7+8+9+10
[root@centos8 ~]# seq -s + 10 > rs.txt;bc < rs.txt
55
等同于
[root@centos8 ~]# bc <<< `seq -s + 10`
55

指令回传值$?  与&&  或||

若前一个命令执行结果为正确,在linux下会回传一个 $? = 0 的值,错误为1

&& 代表 and ,并且;

|| 代表 or,或者;

通常情况下判断式为三个,通常写作如此  command1 && command2 || command2  

#测试当前目录下ceshi目录是否存在,若存在创建/ceshi/aaa文件

[root@wzy data]#ls ./ceshi && touch ./ceshi/aaa
ls: cannot access './ceshi': No such file or directory
[root@wzy data]#mkdir ceshi
[root@wzy data]#ls ./ceshi && touch ./ceshi/aaa
[root@wzy data]#ls ./ceshi
aaa

#测试当前目录下tmp/abc目录是否存在,若不存在则创建tmp/abc,若存在则无操作

root@wzy data]#ls tmp/abc || mkdir -p tmp/abc
[root@wzy data]#ls
tmp
[root@wzy data]#ls tmp/
abc

#使用三联判断式

[root@wzy data]#ls tmp/abc || mkdir -p tmp/abc && touch tmp/abc/one
ls: cannot access 'tmp/abc': No such file or directory
[root@wzy data]#ls tmp/abc/one 
tmp/abc/one 

管道命令 |

管道命令仅能处理由前一个指令传来的正确信息,即standard output的信息,对于standard errror没有直接处理能力,会予以忽略

选取命令

cut:取出一行信息中目标部分

cut -d ’分割字符’ -f 第几段     用于有特定分割字符

-d:后面接分割字符,与-f一起使用

-f:依据-d的分割字符将一段信息分为数段,用-f取出第几段

cut -c 字符区间      用于排列整齐信息

-c:以字符的单位取出固定字符区间

#取出PATH变量中以:分割后的第五段字符

[root@wzy ~]#echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
[root@wzy ~]#echo ${PATH} | cut -d ':' -f 5
/root/bin

#取出PATH变量中以:分割后的第三段和第五段字符

[root@wzy ~]#echo ${PATH} | cut -d ':' -f 3,5
/usr/sbin:/root/bin

#将export输出的前五行信息,取出第12字符以后的所有字符串

[root@wzy ~]#export | head -5
declare -x DBUS_SESSION_BUS_ADDRESS="unix:path=/run/user/0/bus"
declare -x DISPLAY="localhost:10.0"
declare -x HISTCONTROL="ignoredups"
declare -x HISTSIZE="1000"
declare -x HOME="/root"
[root@wzy ~]#export | head -5 | cut -c 12-
DBUS_SESSION_BUS_ADDRESS="unix:path=/run/user/0/bus"
DISPLAY="localhost:10.0"
HISTCONTROL="ignoredups"
HISTSIZE="1000"
HOME="/root"

#将last命令显示的前五行登录者信息中仅留下用户大名

[root@wzy ~]#last | head -5
root     pts/0        192.168.29.1     Sat Apr 15 10:19   still logged in
wenzi    pts/0        192.168.29.1     Sat Apr 15 10:09 - 10:19  (00:09)
root     pts/0        192.168.29.1     Sat Apr 15 10:01 - 10:09  (00:07)
wenzi    pts/0        192.168.29.1     Sat Apr 15 10:00 - 10:01  (00:00)
root     pts/0        192.168.29.1     Sat Apr 15 09:03 - 09:59  (00:56)
[root@wzy ~]#last | head -5 | cut -d ' ' -f 1
root
wenzi
root
wenzi
root

grep:分析一行信息,若该行有目标信息则取出该行

grep [-acinv] [--color=auto] '搜寻字符串' 文件名

-a:将binary文件以text文件的方式搜寻数据

-c:计算找到“搜寻字符串”的次数

-i:忽略大小写差异

-n:输出行号

-v:反向选择,即没有“搜寻字符串”的行

--color=auto:可以将找到的关键字部分加上颜色高亮显示

[root@wzy ~]#last | head -5
root     pts/0        192.168.29.1     Sat Apr 15 10:19   still logged in
wenzi    pts/0        192.168.29.1     Sat Apr 15 10:09 - 10:19  (00:09)
root     pts/0        192.168.29.1     Sat Apr 15 10:01 - 10:09  (00:07)
wenzi    pts/0        192.168.29.1     Sat Apr 15 10:00 - 10:01  (00:00)
root     pts/0        192.168.29.1     Sat Apr 15 09:03 - 09:59  (00:56)

#过滤出含有root用户行
[root@wzy ~]#last | head -5 | grep 'root'
root     pts/0        192.168.29.1     Sat Apr 15 10:19   still logged in
root     pts/0        192.168.29.1     Sat Apr 15 10:01 - 10:09  (00:07)
root     pts/0        192.168.29.1     Sat Apr 15 09:03 - 09:59  (00:56)

#过滤出不含有root用户行
[root@wzy ~]#last | head -5 | grep -v 'root'
wenzi    pts/0        192.168.29.1     Sat Apr 15 10:09 - 10:19  (00:09)
wenzi    pts/0        192.168.29.1     Sat Apr 15 10:00 - 10:01  (00:00)

排序命令

sort

sort [-fbMnrtuk] [ file or stdin ]

-f:忽略大小写,例如A和a视为编码相同

-b:忽略最前面的空格符部分

-M:以月份名字排序,例如JAN,DEC等排序方法

-n:以纯数字进行排序,默认以文字形态排序

-r:反向排序

-u:即uniq去除重复,相同的数据仅显示一行

-t:分隔符,默认以tab键分割

-k:以某个区间排序

#默认以文字形态排序;sort预设以第一个数据排序,如adm和avahi账号顺序

[root@wzy ~]#cat /etc/passwd | sort 
adm:x:3:4:adm:/var/adm:/sbin/nologin
avahi:x:70:70:Avahi mDNS/DNS-SD Stack:/var/run/avahi-daemon:/sbin/nologin
bin:x:1:1:bin:/bin:/sbin/nologin
chrony:x:993:988::/var/lib/chrony:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin

#/etc/passwd默认以:分隔,使以第三栏排序

[root@wzy ~]#cat /etc/passwd | sort -t ':' -k 3
root:x:0:0:root:/root:/bin/bash
wenzi:x:1000:1001:wenzi:/home/wenzi:/bin/bash
qemu:x:107:107:qemu user:/:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin


#并使用数字排序

[root@wzy ~]#cat /etc/passwd | sort -t ':' -k 3 -n
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin

#利用last,将输出的数据仅取账号,并加以排序.。(第一行空格是last默认字符,可忽略)

[root@wzy ~]#last | cut -d ' ' -f 1 | sort

reboot
reboot
root

统计日志访问量

[root@centos8 data]#cut -d" " -f1 /var/log/nginx/access_log | sort -u | wc -l

uniq

 uniq [选项] [文件]

-i:忽略大小写

-c:计数,显示某行连续重复出现的次数,所以是先 sort 再 uniq -c

-d:仅显示重复过的行

-u:仅显示不曾重复的行

常和sort命令一起使用:sort userlist.txt | uniq -c

#使用last仅将账号列出,进行排序后去重,并显示每个人的登录次数。

[root@wzy ~]#last | cut -d ' ' -f 1 | sort | uniq -c
      1 
     15 reboot
      1 roo
     32 root
      1 wenzi
      1 wtmp

wc

 wc [-lwm]

-l:多少行

-w:多少字数

-m:多少字符数,空格、回车也算一个字符

-c:多少字节数

-L:显示一个文件中最长行的长度

[root@wzy ~]#cat test.txt 
 aab c
dd
[root@wzy ~]#wc -c test.txt 
10 test.txt
[root@wzy ~]#wc -m test.txt 
10 test.txt
[root@wzy ~]#wc -L test.txt 
6 test.txt
[root@wzy ~]#wc -l test.txt 
2 test.txt
[root@wzy ~]#wc -w test.txt 
3 test.txt
[root@wzy ~]#cat -A test.txt 
 aab c$
dd$

[root@centos8 data]#cat cs.txt
1 zs    # 1是1个字节、空格是1个字节、z是一个字节、s是一个字节、换行符是一个字节,此
2 ls        行共5个字节
3 w
[root@centos8 data]#cat ab.txt
1 zs
2 ls
3 王    #汉字是3个字节,此行共6个字节
[root@centos8 data]#wc cs.txt
 3  6 14 cs.txt
[root@centos8 data]#wc ab.txt
 3  6 16 ab.txt

双重重定向

tee:同时将数据流分送到文件和屏幕

tee [-a] file

-a:以追加的方式将数据加入file中。默认是覆盖

#取last前五行存到last.txt文件并在屏幕上仅显示前五行的账号

[root@wzy ~]#last | head -5 | tee last.txt | cut -d ' ' -f 1 
root
root
root
root
root
[root@wzy ~]#cat last.txt 
root     pts/0        192.168.29.1     Sun Apr 23 01:42   still logged in
root     pts/2        192.168.29.1     Sat Apr 22 16:16 - 01:14  (08:57)
root     pts/1        192.168.29.1     Sat Apr 22 16:16 - 16:16  (00:00)
root     pts/0        192.168.29.1     Sat Apr 22 16:15 - 16:16  (00:00)
root     pts/0        192.168.29.1     Thu Apr 20 07:00 - 07:01  (00:00)

字符转换命令

tr

tr [-ds] '字符串'

-d:删除讯息中的字符串

-s:把连续重复的字符以单独一个字符表示

#将所有小写变为大写

[root@wzy ~]#last | head -5 | tr '[a-z]' '[A-Z]'
ROOT     PTS/0        192.168.29.1     SUN APR 23 01:42   STILL LOGGED IN
ROOT     PTS/2        192.168.29.1     SAT APR 22 16:16 - 01:14  (08:57)
ROOT     PTS/1        192.168.29.1     SAT APR 22 16:16 - 16:16  (00:00)
ROOT     PTS/0        192.168.29.1     SAT APR 22 16:15 - 16:16  (00:00)
ROOT     PTS/0        192.168.29.1     THU APR 20 07:00 - 07:01  (00:00)

#将分割符:删除

[root@wzy ~]#cat /etc/passwd | head -5 | tr -d ':'
rootx00root/root/bin/bash
binx11bin/bin/sbin/nologin
daemonx22daemon/sbin/sbin/nologin
admx34adm/var/adm/sbin/nologin
lpx47lp/var/spool/lpd/sbin/nologin

col

col [-xb]

-x:将tab键转换成对等的空格键。Tab以^I表示

root@wzy ~]#cat -A abcd 
abc d^Ie$
[root@wzy ~]#cat abcd | col -x | cat -A | more
abc d   e$

join:两个文件中有相同数据的行,才将它加在一起

join [-til2] file1 file2

-t:join默认以空格符分隔数据,并且对比第一个字段的数据,如果两个文件相同,则将两笔数据联成一行,且第一个字段放在第一个。

-i:忽略大小写

-1:数字1,表示第一个文件用某个字段分析

-2:数字2,表示第二个文件用某个字段分析

使用join前需要事先进行排序

#用root的身份,将/etc/passwd与/etc/shadow相关数据整合为一行

[root@wzy ~]#head -n 3 /etc/passwd /etc/shadow
==> /etc/passwd <==
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin

==> /etc/shadow <==
root:$6$pZLLx.uz1Qxz9yqu$MqVJwUTPCW6rM7TRo/O8H8ZXzIyEZw1biH/dORoXigqglsmIsS6xBFqCNVx/2rFqAnuKSqF9LpfIq7jOE9498.::0:99999:7:::
bin:*:18358:0:99999:7:::
daemon:*:18358:0:99999:7:::
[root@wzy ~]#join -t ':' /etc/passwd /etc/shadow | head -n 3
root:x:0:0:root:/root:/bin/bash:$6$pZLLx.uz1Qxz9yqu$MqVJwUTPCW6rM7TRo/O8H8ZXzIyEZw1biH/dORoXigqglsmIsS6xBFqCNVx/2rFqAnuKSqF9LpfIq7jOE9498.::0:99999:7:::
bin:x:1:1:bin:/bin:/sbin/nologin:*:18358:0:99999:7:::
daemon:x:2:2:daemon:/sbin:/sbin/nologin:*:18358:0:99999:7:::


#/etc/passwd第四个字段是GID,/etc/group第三个字段是GID,如何整合两个文件

[root@wzy ~]#head -n 3 /etc/passwd /etc/group
==> /etc/passwd <==
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin

==> /etc/group <==
root:x:0:
bin:x:1:
daemon:x:2:
[root@wzy ~]#join -t ':' -1 4 /etc/passwd -2 3 /etc/group | head -n 3
join: /etc/passwd:6: is not sorted: sync:x:5:0:sync:/sbin:/bin/sync
0:root:x:0:root:/root:/bin/bash:root:x:
1:bin:x:1:bin:/bin:/sbin/nologin:bin:x:
2:daemon:x:2:daemon:/sbin:/sbin/nologin:daemon:x:
join: /etc/group:11: is not sorted: wheel:x:10:roo,wenzi

paste:将两行贴在一起,且中间以tab键隔开,无需对比相关性

paste [-d] file1 file2

-d:后可接分隔字符,默认以tab键隔开

-:如果file部分写成-,表示来自标准输入

#将/etc/passwd与/etc/shadow同一行贴在一起且取前3行

[root@wzy ~]#paste /etc/passwd /etc/shadow | head -3
root:x:0:0:root:/root:/bin/bash    root:$6$pZLLx.uz1Qxz9yqu$MqVJwUTPCW6rM7TRo/O8H8ZXzIyEZw1biH/dORoXigqglsmIsS6xBFqCNVx/2rFqAnuKSqF9LpfIq7jOE9498.::0:99999:7:::
bin:x:1:1:bin:/bin:/sbin/nologin    bin:*:18358:0:99999:7:::
daemon:x:2:2:daemon:/sbin:/sbin/nologin    daemon:*:18358:0:99999:7:::

#将/etc/group读出,然后与上述贴在一起且取前三行。注意-符号
[root@wzy ~]#cat /etc/group | paste /etc/passwd /etc/shadow - | head -n 3
root:x:0:0:root:/root:/bin/bash    root:$6$pZLLx.uz1Qxz9yqu$MqVJwUTPCW6rM7TRo/O8H8ZXzIyEZw1biH/dORoXigqglsmIsS6xBFqCNVx/2rFqAnuKSqF9LpfIq7jOE9498.::0:99999:7:::    root:x:0:
bin:x:1:1:bin:/bin:/sbin/nologin    bin:*:18358:0:99999:7:::    bin:x:1:
daemon:x:2:2:daemon:/sbin:/sbin/nologin    daemon:*:18358:0:99999:7:::    daemon:x:2:

[root@centos8 data]#seq 5 > a.txt
[root@centos8 data]#cat a.txt
1
2
3
4
5
[root@centos8 data]#echo -e "a\nb\nc\nd\ne" > b.txt
[root@centos8 data]#cat b.txt
a
b
c
d
e
[root@centos8 data]#paste a.txt b.txt
1       a
2       b
3       c
4       d
5       e
[root@centos8 data]#paste -d":" a.txt b.txt
1:a
2:b
3:c
4:d
5:e
[root@centos8 data]#paste -s a.txt
1       2       3       4       5
[root@centos8 data]#paste -s a.txt b.txt
1       2       3       4       5
a       b       c       d       e
[root@centos8 data]#paste -s -d":" a.txt b.txt
1:2:3:4:5
a:b:c:d:e

批量更改用户密码

[root@centos8 data]#cat name.txt
zhangsan
lisi
[root@centos8 data]#cat pwd.txt
zs
ls
[root@centos8 data]#paste -d ":" name.txt pwd.txt
zhangsan:zs
lisi:ls
[root@centos8 data]#paste -d ":" name.txt pwd.txt | chpasswd

expand

expand [-t] file

-t:后面可接数字自定义一个tab键代表多少空格键。通常一个tab键用8个空格键取代,

# ^I表示tab键 ¥表示回车 

[root@wzy ~]#grep "^MANPATH" /etc/man_db.conf | head -3
MANPATH_MAP    /bin            /usr/share/man
MANPATH_MAP    /usr/bin        /usr/share/man
MANPATH_MAP    /sbin            /usr/share/man
[root@wzy ~]#grep "^MANPATH" /etc/man_db.conf | head -3 | cat -A
MANPATH_MAP^I/bin^I^I^I/usr/share/man$
MANPATH_MAP^I/usr/bin^I^I/usr/share/man$
MANPATH_MAP^I/sbin^I^I^I/usr/share/man$

分割文件

split:依据文件大小分割文件

split [-bl] file PREFIX

-b:后面可接欲分割成的文件大小 ,默认-b表示以b字节为单位。可加单位,如k、m等

-l:以行数分割

PREFIX:代表前导符,可作为分割文件的前导文字

#以文件大小分割

[root@wzy ~]#ll -h
-rwxr-xr-x  1 root root 1.2K Mar 29 22:06 initenv.sh

[root@wzy ~]#split -b 1k initenv.sh initenv

[root@wzy ~]#ll -h
-rw-r--r--  1 root root 1.0K Apr 23 04:06 initenvaa
-rw-r--r--  1 root root  196 Apr 23 04:06 initenvab
-rwxr-xr-x  1 root root 1.2K Mar 29 22:06 initenv.sh

#合并

[root@wzy ~]#cat initenva* >> initenv.txt

#以行数分割

[root@wzy ~]#cat abc
aa
bb
cc
dd
[root@wzy ~]#split -l 2 abc abc
[root@wzy ~]#ll
total 40
-rw-r--r--  1 root root   12 Apr 23 04:15 abc
-rw-r--r--  1 root root    6 Apr 23 04:16 abcaa
-rw-r--r--  1 root root    6 Apr 23 04:16 abcab

比较文件

diff

-u:输出统一的diff格式文件。最适用于补丁文件

[root@centos8 data]#cat a.txt
1
12
123
1234
12345
[root@centos8 data]#cat b.txt
1
12a
123
123
12345
b
[root@centos8 data]#diff -u a.txt b.txt   表示以a为标准
--- a.txt       2023-12-08 05:27:57.639220402 +0800        代表a.txt文件信息
+++ b.txt       2023-12-08 05:28:22.221067369 +0800        代表b.txt文件信息
@@ -1,5 +1,6 @@        表示比较a的1-5行;比较b的1-6行
 1       
-12       
+12a       
+123   
 123
-1234
 12345
+b

格式化打印

printf

printf '打印格式' 实际内容

\n:换行符,输出新的一行

\r:回车符,enter键

\t:水平制表符,tab键

\v:垂直制表符

\b:退后一格

%s:表示任意长度的字符串

%ns:n是数字,s是字符串,即多少个字符

%ni:n是数字,i是数字,即多少整数字数

%N.nf:n、N都是数字,f是浮点数。假设共要十个位数,小数点有两位,即%10,2f

[root@centos8 data]#printf "%s \t %s \t %s \t %s\n" "姓名" "性别" "年龄" "分数" "小明" "男" "18" "60" "小红" "女" "19" "82.5" "小蓝" "男" "18" "98.75" > list.txt
[root@centos8 data]#cat list.txt
姓名     性别    年龄    分数
小明     男      18      60
小红     女      19      82.5
小蓝     男      18      98.75


[root@centos8 data]#printf '%5s %5s %5i \t %4.2f \n' `cat list.txt | awk 'NR>1 {print $0}'`
小明   男    18          60.00  将小数点后的两位也显示出来
小红   女    19          82.50
小蓝   男    18          98.75
[root@centos8 data]#printf '%5s %5s %5i \t %4.1f \n' `cat list.txt | awk 'NR>1 {print $0}'`
小明   男    18          60.0
小红   女    19          82.5
小蓝   男    18          98.8    四舍五入了

参数代换

 xargs

xargs [-Oepn] command

-O:如果输入的有特殊字符,此参数可将其视为普通文本

-e:及EOF(end of file),后可接一个字符串,当xargs分析到此字符串时就会停止工作。-e和字符串之间没有空格。

-p:执行每个指令的参数时都会询问

-n:后接次数,每次command执行时要使用几个参数

当xargs后没有接任何指令时,默认以echo输出

#错误示范。虽然$()可预先取得参数,但是id命令仅能接收一个参数

[root@wzy ~]#id $(cut -d ':' -f 1 /etc/passwd | head -n 3)

#错误示范。id不是管线命令,显示结果不是想要的

[root@wzy ~]#cut -d ':' -f 1 /etc/passwd | head -3 | id
uid=0(root) gid=0(root) groups=0(root)
#正确写法。-n指定每次传递一个参数

[root@wzy ~]#cut -d ':' -f 1 /etc/passwd | head -3 | xargs -p -n 1 id
id root ?...y
uid=0(root) gid=0(root) groups=0(root)
id bin ?...y
uid=1(bin) gid=1(bin) groups=1(bin)
id daemon ?...y
uid=2(daemon) gid=2(daemon) groups=2(daemon)

安装复制文件

install

install功能相当于cp、chmod、chown、chgrp、mkdir等相关工具集合

install [OPTION]... [-T] SOURCE DEST
install [OPTION]... SOURCE... DIRECTORY
install [OPTION]... -t DIRECTORY SOURCE...
install [OPTION]... -d DIRECTORY...

Option:

-m 权限,默认755

-o 所属主

-g 所属组

-d 目录

复制/etc/passwd 文件到 /data 目录下,并将passwd文件权限设置为666,属主为wang,属组root

[root@centos8 data]# install -m 666 -o wang -g root /etc/passwd /data/

[root@centos8 data]# ll
total 4
-rw-rw-rw- 1 wang root 2658 Nov 22 22:46 passwd
[root@centos8 data]# ll /etc/passwd
-rw-r--r--. 1 root root 2658 Nov 14 01:17 /etc/passwd

关于减号-的用途

在管道命令中,常会使用到前一个指令的stdout作为本次的stdin,某些命令需要文件名来处理时可用减号 – 来替代stdout或stdin

mkdir /tmp/homeback

tar -cv -f /home | tar -xv -f - -C /tmp/homeback

我将/home中数据打包,但打包后数据不是记录到文件,而是传递到stdout;经过管道命令将 tar -cv -f /home 结果传递给 tar -xv -f – 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值