2.7 变量
2.7.1 变量
变量表示命名的内存空间,将数据放在内存空间中,通过变量名引用,获取数据
2.7.2 变量类型
变量类型:
- 内置变量,如:PS1,PATH,UID,HOSTNAME,$ , B A S H P I D , P P I D , ,BASHPID,PPID, ,BASHPID,PPID,?,HISTSIZE
- 用户自定义变量
不同的变量存放的数据不同,决定了以下
- 数据存储方式
- 参与的运算
- 表示的数据范围
变量数据类型:
- 字符
- 数值:整型、浮点型,bash 不支持浮点数
2.7.3 编程语言分类
静态和动态语言
- 静态编译语言:使用变量前,先声明变量类型,之后类型不能改变,在编译时检查,如:java,c
- 动态编译语言:不用事先声明,可随时改变类型,如:bash,Python
强类型和弱类型语言
- 强类型语言:不同类型数据操作,必须经过强制转换才同一类型才能运算,如java , c# ,python
如:参考以下 python 代码
print('raymond'+ 10) #提示出错,不会自动转换类型
print('raymond'+str(10)) #结果为raymond10,需要显示转换类型
- 弱类型语言:语言的运行时会隐式做数据类型转换。无须指定类型,默认均为字符型;参与运算会自动进行隐式类型转换;变量无须事先定义可直接调用
如:bash ,php,javascript
2.7.4 Shell 中变量命名法则
2.7.4.1 命名要求
- 区分大小写
- 不能使程序中的保留字和内置变量:如:if, for
- 只能使用数字、字母及下划线,且不能以数字开头,注意:不支持短横线 “ - ”,和主机名相反
2.7.4.2 命名习惯
- 见名知义,用英文单词命名,并体现出实际作用,不要用简写,如:ATM
- 变量名大写
- 局部变量小写
- 函数名小写
- 大驼峰StudentName
- 小驼峰studentName
- 下划线: student_name
2.7.5 变量定义和引用
变量的生效范围等标准划分变量类型
- 普通变量:生效范围为当前shell进程;对当前shell之外的其它shell进程,包括当前shell的子shell进程均无效
- 环境变量:生效范围为当前shell进程及其子进程
- 本地变量:生效范围为当前shell进程中某代码片断,通常指函数
变量赋值:
name='value'
value 可以是以下多种形式
直接字串:name='root'
变量引用:name="$USER"
命令引用:name=`COMMAND` 或者 name=$(COMMAND)
注意:变量赋值是临时生效,当退出终端后,变量会自动删除,无法持久保存,脚本中的变量会随着脚本结束,也会自动删除
变量引用:
$name
${name}
弱引用和强引用
- "$name " 弱引用,其中的变量引用会被替换为变量值
- '$name ’ 强引用,其中的变量引用不会被替换为变量值,而保持原字符串
范例:
[root@rocky8 data]# name=raymond
[root@rocky8 data]# echo name
name
[root@rocky8 data]# echo $name
raymond
[root@rocky8 data]# echo "$name"
raymond
[root@rocky8 data]# echo '$name'
$name
[root@rocky8 data]# echo my name is $name
my name is raymond
范例:变量引用
[root@rocky8 data]# age=18
[root@rocky8 data]# echo $name
raymond
[root@rocky8 data]# echo $age
18
[root@rocky8 data]# echo $name:$age
raymond:18
[root@rocky8 data]# echo $name_$age
18
#用下划线不行
[root@rocky8 data]# echo $name_
#因为他把_ 下划线当做文件名
[root@rocky8 data]# echo ${name}_$age
raymond_18
#用{} 花括号 把前面的变量引起来就可以
[root@rocky8 data]# echo $name'_'$age
raymond_18
#把下划线用单引号引起来也可以
[root@rocky8 data]# echo ${name}_${age}
raymond_18
#生产用为了不发生边界区分引起问题,一般变量都加上{} 花括号引起来
[root@rocky8 data]# unset name #unset 删除变量
[root@rocky8 data]# echo $name
#删除后变量就看不到了
[root@rocky8 data]# set |less #set 查看系统定义的变量
BASH=/bin/bash
BASHOPTS=checkwinsize:cmdhist:complete_fullquote:expand_aliases:extquote:force_fignore:histappend:hostcomplete:interactive_comments:login_shell:progcomp:promptvars:sourcepath
BASHRCSOURCED=Y
BASH_ALIASES=()
BASH_ARGC=()
BASH_ARGV=()
BASH_CMDS=()
BASH_LINENO=()
BASH_SOURCE=()
BASH_VERSINFO=([0]="4" [1]="4" [2]="20" [3]="1" [4]="release" [5]="x86_64-redhat-linux-gnu")
BASH_VERSION='4.4.20(1)-release'
CMD=hostname
COLUMNS=143
DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/0/bus
DIRSTACK=()
EUID=0
FILE='/etc/*'
GROUPS=()
HISTCONTROL=ignoredups
HISTFILE=/root/.bash_history
HISTFILESIZE=1000
HISTSIZE=1000
HOME=/root
HOSTNAME=rocky8
HOSTTYPE=x86_64
[root@rocky8 data]# NAME1=raymond
[root@rocky8 data]# NAME2=$NAME1
[root@rocky8 data]# echo $NAME2
raymond
[root@rocky8 data]# echo $NAME1
raymond
[root@rocky8 data]# NAME1=boss
[root@rocky8 data]# echo $NAME1
boss
[root@rocky8 data]# echo $NAME2
raymond
[root@rocky8 data]# name="zhang
wang
li
zhao
ma"
[root@rocky8 data]# echo $name
zhang wang li zhao ma
#一个变量可以存多个值
[root@rocky8 data]# echo "$name"
zhang
wang
li
zhao
ma
#加双引号 就不一样了
范例:变量的各种赋值方式和引用
[root@rocky8 data]# TITLE='cto'
[root@rocky8 data]# echo $TITLE
cto
[root@rocky8 data]# echo I am $TITLE
I am cto
[root@rocky8 data]# echo "I am $TITLE"
I am cto
[root@rocky8 data]# echo 'I am $TITLE'
I am $TITLE
[root@rocky8 data]# NAME=$USER
[root@rocky8 data]# echo $NAME
root
[root@rocky8 data]# USER=`whoami`
[root@rocky8 data]# echo $USER
root
[root@rocky8 data]# FILE=`ls /run`
[root@rocky8 data]# echo $FILE
agetty.reload atd.pid auditd.pid console cron.reboot cryptsetup dbus faillock fsck httpd initctl initramfs lock log mount NetworkManager plymouth rsyslogd.pid sepermit setrans sshd.pid sssd.pid sudo systemd tmpfiles.d tuned udev user utmp vmware
[root@rocky8 data]# FILE=/etc/*
[root@rocky8 data]# echo $FILE
/etc/adjtime /etc/aliases /etc/alternatives /etc/anacrontab /etc/at.deny /etc/audit /etc/authselect /etc/bash_completion.d /etc/bashrc /etc/bindresvport.blacklist /etc/binfmt.d /etc/chkconfig.d /etc/cifs-utils /etc/cron.d /etc/cron.daily /etc/cron.deny /etc/cron.hourly /etc/cron.monthly /etc/crontab /etc/cron.weekly /etc/crypto-policies /etc/crypttab /etc/csh.cshrc /etc/csh.login /etc/dbus-1 /etc/default /etc/depmod.d /etc/DIR_COLORS /etc/DIR_COLORS.256color /etc/DIR_COLORS.lightbgcolor /etc/dnf /etc/dracut.conf /etc/dracut.conf.d /etc/environment /etc/ethertypes /etc/exports /etc/filesystems /etc/firewalld /etc/fstab /etc/fuse.conf /etc/gcrypt /etc/gnupg /etc/GREP_COLORS /etc/groff /etc/group /etc/group- /etc/grub2.cfg /etc/grub.d /etc/gshadow /etc/gshadow- /etc/gss /etc/host.conf /etc/hostname /etc/hosts /etc/httpd /etc/idmapd.conf /etc/init.d /etc/inittab /etc/inputrc /etc/iproute2 /etc/issue /etc/issue.net /etc/kdump /etc/kdump.conf /etc/kernel /etc/krb5.conf /etc/krb5.conf.d /etc/ld.so.cache /etc/ld.so.conf /etc/ld.so.conf.d /etc/libaudit.conf /etc/libibverbs.d /etc/libnl /etc/libreport /etc/libssh /etc/libuser.conf /etc/locale.conf /etc/localtime /etc/login.defs /etc/logrotate.conf /etc/logrotate.d /etc/lsb-release.d /etc/machine-id /etc/magic /etc/mailcap /etc/mail.rc /etc/makedumpfile.conf.sample /etc/man_db.conf /etc/microcode_ctl /etc/mime.types /etc/mke2fs.conf /etc/modprobe.d /etc/modules-load.d /etc/motd /etc/mtab /etc/netconfig /etc/NetworkManager /etc/networks /etc/nftables /etc/nsswitch.conf /etc/nsswitch.conf.bak /etc/openldap /etc/opt /etc/os-release /etc/pam.d /etc/passwd /etc/passwd- /etc/pkcs11 /etc/pki /etc/plymouth /etc/pm /etc/polkit-1 /etc/popt.d /etc/postfix /etc/prelink.conf.d /etc/printcap /etc/profile /etc/profile.d /etc/protocols /etc/rc0.d /etc/rc1.d /etc/rc2.d /etc/rc3.d /etc/rc4.d /etc/rc5.d /etc/rc6.d /etc/rc.d /etc/rc.local /etc/rdma /etc/redhat-lsb /etc/redhat-release /etc/resolv.conf /etc/rhsm /etc/rocky-release /etc/rocky-release-upstream /etc/rpc /etc/rpm /etc/rsyslog.conf /etc/rsyslog.d /etc/rwtab.d /etc/sasl2 /etc/security /etc/selinux /etc/services /etc/sestatus.conf /etc/shadow /etc/shadow- /etc/shells /etc/skel /etc/ssh /etc/ssl /etc/sssd /etc/subgid /etc/subgid- /etc/subuid /etc/subuid- /etc/sudo.conf /etc/sudoers /etc/sudoers.d /etc/sudo-ldap.conf /etc/sysconfig /etc/sysctl.conf /etc/sysctl.d /etc/systemd /etc/system-release /etc/system-release-cpe /etc/tcsd.conf /etc/terminfo /etc/tmpfiles.d /etc/tuned /etc/udev /etc/unbound /etc/vconsole.conf /etc/vimrc /etc/virc /etc/vmware-tools /etc/wgetrc /etc/X11 /etc/xattr.conf /etc/xdg /etc/xinetd.d /etc/yum /etc/yum.conf /etc/yum.repos.d
[root@rocky8 data]# seq 10
1
2
3
4
5
6
7
8
9
10
[root@rocky8 data]# NUM=`seq 10`
[root@rocky8 data]# echo $NUM
1 2 3 4 5 6 7 8 9 10
[root@rocky8 data]# echo "$NUM"
1
2
3
4
5
6
7
8
9
10
范例:变量的间接赋值和引用
[root@rocky8 data]# TITLE=cto
[root@rocky8 data]# NAME=raymond
[root@rocky8 data]# TITLE=$NAME
[root@rocky8 data]# echo $NAME
raymond
[root@rocky8 data]# echo $TITLE
raymond
[root@rocky8 data]# NAME=boss
[root@rocky8 data]# echo $NAME
boss
[root@rocky8 data]# echo $TITLE
raymond
范例:变量追加值
[root@rocky8 data]# TITLE=CTO
[root@rocky8 data]# TITLE+=:raymond
[root@rocky8 data]# echo $TITLE
CTO:raymond
范例:利用变量实现动态命令
[root@rocky8 data]# CMD=hostname
[root@rocky8 data]# $CMD
rocky8
显示已定义的所有变量:
set
删除变量:
unset <name>
范例:
[root@rocky8 data]# NAME=raymond
[root@rocky8 data]# TITLE=ceo
[root@rocky8 data]# echo $NAME $TITLE
raymond ceo
[root@rocky8 data]# unset NAME TITLE
[root@rocky8 data]# echo $NAME $TITLE
范例:
[root@rocky8 data]# vim backup.sh
#!/bin/bash
#
#**********************************************************************************************
#Author: Raymond
#QQ: 88563128
#Date: 2021-10-09
#FileName: backup.sh
#URL: raymond.blog.csdn.net
#Description: The test script
#Copyright (C): 2021 All rights reserved
#*********************************************************************************************
COLOR='\E[1;31m'
COLOR_END='\E[0m'
SRC=/etc
DEST=/data
echo -e ${COLOR}Starting backup...${COLOR_END}
sleep 2
cp -av $SRC $SRC$DEST`date +%F_%H-%M-%S`
echo -e ${COLOR}Backup is finished${COLOR_END}
范例:显示系统信息
[root@rocky8 data]# vim systeminfo.sh
#!/bin/bash
#
#**********************************************************************************************
#Author: Raymond
#QQ: 88563128
#Date: 2021-10-09
#FileName: systeminfo.sh
#URL: raymond.blog.csdn.net
#Description: The test script
#Copyright (C): 2021 All rights reserved
#*********************************************************************************************
RANDOM_COLOR="\E[1;"$[RANDOM%7+31]"m"
GREEN="echo -e \E[1;32m"
COLOR_END="\E[0m"
ETHNAME=`ifconfig |head -1| tr -s ":" " "|cut -d" " -f 1`
$GREEN----------------------Host systeminfo--------------------$COLOR_END
echo -e "HOSTNAME: $RANDOM_COLOR`hostname`$COLOR_END"
echo -e "IPADDR: $RANDOM_COLOR` ifconfig $ETHNAME|grep -Eo '([0-9]{1,3}\.){3}[0-9]{1,3}' |head -n1`$COLOR_END"
#echo -e "IPADDR: $RANDOM_COLOR` hostname -I`$COLOR_END"
echo -e "OSVERSION: $RANDOM_COLOR`cat /etc/redhat-release`$COLOR_END"
echo -e "KERNEL: $RANDOM_COLOR`uname -r`$COLOR_END"
echo -e "CPU: $RANDOM_COLOR`lscpu|grep '^Model name'|tr -s ' '|cut -d : -f2`$COLOR_END"
echo -e "MEMORY: $RANDOM_COLOR`free -h|grep Mem|tr -s ' ' : |cut -d : -f2`$COLOR_END"
echo -e "DISK: $RANDOM_COLOR`lsblk |grep '^sd' |tr -s ' ' |cut -d " " -f4`$COLOR_END"
$GREEN---------------------------------------------------------$COLOR_END
2.7.6 练习:
1、编写脚本 systeminfo.sh,显示当前主机系统信息,包括:主机名,IPv4地址,操作系统版本,内核版本,CPU型号,内存大小,硬盘大小
2、编写脚本 backup.sh,可实现每日将/etc/目录备份到/backup/etcYYYY-mm-dd中
3、编写脚本 disk.sh,显示当前硬盘分区中空间利用率最大的值
4、编写脚本 links.sh,显示正连接本主机的每个远程主机的IPv4地址和连接数,并按连接数从大到小排序
2.7.7 环境变量
环境变量:
- 可以使子进程(包括孙子进程)继承父进程的变量,但是无法让父进程使用子进程的变量
- 一旦子进程修改从父进程继承的变量,将会新的值传递给孙子进程
- 一般只在系统配置文件中使用,在脚本中较少使用
变量声明和赋值:
#声明并赋值
export name=VALUE
declare -x name=VALUE
#或者分两步实现
name=VALUE
export name
变量引用:
$name
${name}
显示所有环境变量:
env
printenv
export
declare -x
删除变量:
unset name
bash内建的环境变量
PATH
SHELL
USER
UID
HOME
PWD
SHLVL #shell的嵌套层数,即深度
LANG
MAIL
HOSTNAME
HISTSIZE
_ #下划线 表示前一命令的最后一个参数
范例:
[root@rocky8 data]# echo $BASHPID
1566
[root@rocky8 data]# pstree -p |grep bash
|-sshd(756)---sshd(1553)---sshd(1565)---bash(1566)-+-grep(1832)
[root@rocky8 data]# bash
[root@rocky8 data]# echo $BASHPID
1833
[root@rocky8 data]# pstree -p |grep bash
|-sshd(756)---sshd(1553)---sshd(1565)---bash(1566)---bash(1833)-+-grep(1853)
[root@rocky8 data]# title=ceo
[root@rocky8 data]# echo $title
ceo
[root@rocky8 data]# bash
[root@rocky8 data]# echo $BASHPID
1854
[root@rocky8 data]# pstree -p |grep bash
|-sshd(756)---sshd(1553)---sshd(1565)---bash(1566)---bash(1833)---bash(1854)-+-grep(1874)
[root@rocky8 data]# echo $title
#定义的变量只对当前shell有效,不能跨子shell有效
[root@rocky8 data]# exit
exit
[root@rocky8 data]# echo $title
ceo
[root@rocky8 data]# export title
[root@rocky8 data]# echo $title
ceo
[root@rocky8 data]# bash
[root@rocky8 data]# echo $BASHPID
1875
[root@rocky8 data]# pstree -p |grep bash
|-sshd(756)---sshd(1553)---sshd(1565)---bash(1566)---bash(1833)---bash(1875)-+-grep(1895)
[root@rocky8 data]# echo $title
ceo
[root@rocky8 data]# bash
[root@rocky8 data]# echo $BASHPID
1896
[root@rocky8 data]# echo $title
ceo
[root@rocky8 data]# pstree -p |grep bash
|-sshd(756)---sshd(1553)---sshd(1565)---bash(1566)---bash(1833)---bash(1875)---bash(1896)-+-grep(1916)
#要想变量继承,就需要export 设置全局变量
[root@rocky8 data]# title=seccretary
[root@rocky8 data]# echo $title
seccretary
[root@rocky8 data]# bash
[root@rocky8 data]# echo $BASHPID
1918
[root@rocky8 data]# pstree -p |grep bash
|-sshd(756)---sshd(1553)---sshd(1565)---bash(1566)---bash(1833)---bash(1875)---bash(1896)---bash(1918)-+-grep(1938)
[root@rocky8 data]# echo $title
seccretary
[root@rocky8 data]# exit
exit
[root@rocky8 data]# echo $BASHPID
1896
[root@rocky8 data]# pstree -p |grep bash
|-sshd(756)---sshd(1553)---sshd(1565)---bash(1566)---bash(1833)---bash(1875)---bash(1896)-+-grep(1940)
[root@rocky8 data]# echo $title
seccretary
[root@rocky8 data]# exit
exit
[root@rocky8 data]# echo $BASHPID
1875
[root@rocky8 data]# pstree -p |grep bash
|-sshd(756)---sshd(1553)---sshd(1565)---bash(1566)---bash(1833)---bash(1875)-+-grep(1942)
[root@rocky8 data]# echo $title
ceo
#继承变量,如果在中间改变赋值,只影响它的下级Shell,不会影响他的父shell
[root@rocky8 data]# declare -x #显示所有的全局变量
declare -x DBUS_SESSION_BUS_ADDRESS="unix:path=/run/user/0/bus"
declare -x HISTCONTROL="ignoredups"
declare -x HISTSIZE="1000"
declare -x HOME="/root"
declare -x HOSTNAME="rocky8"
declare -x LANG="en_US.UTF-8"
declare -x LESSOPEN="||/usr/bin/lesspipe.sh %s"
declare -x LOGNAME="root"
declare -x 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:"
declare -x MAIL="/var/spool/mail/root"
declare -x OLDPWD="/root"
declare -x PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin"
declare -x PWD="/data"
declare -x SHELL="/bin/bash"
declare -x SHLVL="3"
declare -x SSH_CLIENT="172.31.0.1 58709 22"
declare -x SSH_CONNECTION="172.31.0.1 58709 172.31.1.8 22"
declare -x SSH_TTY="/dev/pts/0"
declare -x TERM="linux"
declare -x USER="root"
declare -x XDG_RUNTIME_DIR="/run/user/0"
declare -x XDG_SESSION_ID="1"
declare -x title="ceo"
# declare -x 和export 是等价的
[root@centos8 ~]# unset title
#删除环境变量
#别名在脚本中不能用
#系统的环境变量,可能会在某些环境调用,执行的效果不同
2.7.7 只读变量
只读变量:只能声明定义,但后续不能修改和删除,即常量
声明只读变量:
readonly name
declare -r name
查看只读变量:
readonly [-p]
declare -r
范例:
[root@rocky8 data]# readonly PI=3.14159 #定义常量
[root@rocky8 data]# echo $PI
3.14159
[root@rocky8 data]# readonly #查看常量
declare -r BASHOPTS="checkwinsize:cmdhist:complete_fullquote:expand_aliases:extquote:force_fignore:histappend:hostcomplete:interactive_comments:progcomp:promptvars:sourcepath"
declare -ir BASHPID="1875"
declare -ar BASH_VERSINFO=([0]="4" [1]="4" [2]="20" [3]="1" [4]="release" [5]="x86_64-redhat-linux-gnu")
declare -ir EUID="0"
declare -r PI="3.14159"
declare -ir PPID="1833"
declare -r SHELLOPTS="braceexpand:emacs:hashall:histexpand:history:interactive-comments:monitor"
declare -ir UID="0"
[root@rocky8 data]# declare -r #查看常量,和readonly 一样
declare -r BASHOPTS="checkwinsize:cmdhist:complete_fullquote:expand_aliases:extquote:force_fignore:histappend:hostcomplete:interactive_comments:progcomp:promptvars:sourcepath"
declare -ir BASHPID="1875"
declare -ar BASH_VERSINFO=([0]="4" [1]="4" [2]="20" [3]="1" [4]="release" [5]="x86_64-redhat-linux-gnu")
declare -ir EUID="0"
declare -r PI="3.14159"
declare -ir PPID="1833"
declare -r SHELLOPTS="braceexpand:emacs:hashall:histexpand:history:interactive-comments:monitor"
declare -ir UID="0"
[root@rocky8 data]# PI=3.14
bash: PI: readonly variable
#常量不能更改
[root@rocky8 data]# echo $PI
3.14159
[root@rocky8 data]# unset PI
bash: unset: PI: cannot unset: readonly variable
#常量也不能删除
[root@rocky8 data]# exit
exit
#退出当前shell,常量就没有了
[root@rocky8 data]# echo $PI
[root@rocky8 data]# 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_CONNECTION=172.31.0.1 58709 172.31.1.8 22
LANG=en_US.UTF-8
HISTCONTROL=ignoredups
HOSTNAME=rocky8
OLDPWD=/root
XDG_SESSION_ID=1
USER=root
PWD=/data
HOME=/root
SSH_CLIENT=172.31.0.1 58709 22
SSH_TTY=/dev/pts/0
MAIL=/var/spool/mail/root
SHELL=/bin/bash
TERM=linux
SHLVL=2
title=ceo
LOGNAME=root
DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/0/bus
XDG_RUNTIME_DIR=/run/user/0
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
HISTSIZE=1000
LESSOPEN=||/usr/bin/lesspipe.sh %s
_=/usr/bin/env
#_ 下划线也是一个变量
[root@rocky8 data]# echo a b c
a b c
[root@rocky8 data]# echo $_
c
#_ 下划线 代表前一个命令的最后一个字符串,这是系统自带的
2.7.8 位置变量
位置变量:在bash shell中内置的变量, 在脚本代码中调用通过命令行传递给脚本的参数
$1, $2, ... 对应第1个、第2个等参数,shift [n]换位置
$0 命令本身,包括路径
$* 传递给脚本的所有参数,全部参数合为一个字符串
$@ 传递给脚本的所有参数,每个参数为独立字符串
$# 传递给脚本的参数的个数
注意:$@ $* 只在被双引号包起来的时候才会有差异
清空所有位置变量
set --
范例:
[root@rocky8 data]# cd
[root@rocky8 ~]# mkdir bin
[root@rocky8 ~]# cd bin
[root@rocky8 bin]# vim arg.sh
#!/bin/bash
#
#**********************************************************************************************
#Author: Raymond
#QQ: 88563128
#Date: 2021-10-09
#FileName: arg.sh
#URL: raymond.blog.csdn.net
#Description: The test script
#Copyright (C): 2021 All rights reserved
#*********************************************************************************************
echo 1st arg is $1
echo 2st arg is $2
echo 3st arg is $3
echo all arg is $*
echo all arg is $@
echo all arg number $#
echo the scriptsname is $0
[root@rocky8 bin]# arg.sh a b c
1st arg is a
2st arg is b
3st arg is c
all arg is a b c
all arg is a b c
all arg number 3
the scriptsname is /root/bin/arg.sh #文件名有路径
[root@rocky8 bin]# vim arg.sh
#!/bin/bash
#
#**********************************************************************************************
#Author: Raymond
#QQ: 88563128
#Date: 2021-10-09
#FileName: arg.sh
#URL: raymond.blog.csdn.net
#Description: The test script
#Copyright (C): 2021 All rights reserved
#*********************************************************************************************
echo 1st arg is $1
echo 2st arg is $2
echo 3st arg is $3
echo all arg is $*
echo all arg is $@
echo all arg number $#
echo the scriptsname is `basename $0` #加`bashname $0`
[root@rocky8 bin]# arg.sh a b c
1st arg is a
2st arg is b
3st arg is c
all arg is a b c
all arg is a b c
all arg number 3
the scriptsname is arg.sh #只显示文件名,没有路径
[root@rocky8 bin]# vim arg.sh
#!/bin/bash
#
#**********************************************************************************************
#Author: Raymond
#QQ: 88563128
#Date: 2021-10-09
#FileName: arg.sh
#URL: raymond.blog.csdn.net
#Description: The test script
#Copyright (C): 2021 All rights reserved
#*********************************************************************************************
echo 1st arg is $1
echo 2st arg is $2
echo 3st arg is $3
echo 10st arg is $10
echo 11st arg is $11
echo all arg is $*
echo all arg is $@
echo all arg number $#
echo the scriptsname is `basename $0`
[root@rocky8 bin]# arg.sh {a..z}
1st arg is a
2st arg is b
3st arg is c
10st arg is a0 #第10个参数显示a0
11st arg is a1 #第11个参数显示a1
all arg is a b c d e f g h i j k l m n o p q r s t u v w x y z
all arg is a b c d e f g h i j k l m n o p q r s t u v w x y z
all arg number 26
the scriptsname is arg.sh
[root@rocky8 bin]# vim arg.sh
#!/bin/bash
#
#**********************************************************************************************
#Author: Raymond
#QQ: 88563128
#Date: 2021-10-09
#FileName: arg.sh
#URL: raymond.blog.csdn.net
#Description: The test script
#Copyright (C): 2021 All rights reserved
#*********************************************************************************************
echo 1st arg is $1
echo 2st arg is $2
echo 3st arg is $3
echo 10st arg is ${10} #它把$10,当成$1和0,要当做整体,必须把它用{}花括号括起来,${10}
echo 11st arg is ${11}
echo all arg is $*
echo all arg is $@
echo all arg number $#
echo the scriptsname is `basename $0`
[root@rocky8 bin]# arg.sh {a..z}
1st arg is a
2st arg is b
3st arg is c
10st arg is j #现在就是获取$10的参数了
11st arg is k
all arg is a b c d e f g h i j k l m n o p q r s t u v w x y z
all arg is a b c d e f g h i j k l m n o p q r s t u v w x y z
all arg number 26
the scriptsname is arg.sh
$* 和$@ 区别
$* 传递给脚本所有参数,全部参数合为一个字符串
$@ 传递给脚本所有参数,每个参数为独立字符串
范例:删库跑路之命令rm的安全实现
[root@rocky8 bin]# vim rm.sh
#!/bin/bash
#
#**********************************************************************************************
#Author: Raymond
#QQ: 88563128
#Date: 2021-10-09
#FileName: rm.sh
#URL: raymond.blog.csdn.net
#Description: The test script
#Copyright (C): 2021 All rights reserved
#*********************************************************************************************
WARNING_COLOR="echo -e \E[1;31m"
END_COLOR="\E[0m"
DIR=/tmp/`date +%F_%H-%M-%S`
mkdir $DIR
mv $* $DIR
${WARNING_COLOR}Move $* to $DIR $END
[root@rocky8 bin]# chmod +x rm.sh
[root@rocky8 bin]# alias rm=rm.sh
[root@rocky8 bin]# cd
[root@rocky8 ~]# ls
anaconda-ks.cfg anaconda-screenshots bin
[root@rocky8 ~]# touch {a..c}
[root@rocky8 ~]# rm {a..c}
Move a b c to /tmp/2021-10-09_15-42-36
[root@rocky8 ~]# ll /tmp/2021-10-09_15-42-36
total 0
-rw-r--r-- 1 root root 0 Oct 9 15:42 a
-rw-r--r-- 1 root root 0 Oct 9 15:42 b
-rw-r--r-- 1 root root 0 Oct 9 15:42 c
范例: ∗ 和 *和 ∗和@的区别
[root@rocky8 ~]# vim f1.sh
#!/bin/bash
#
#**********************************************************************************************
#Author: Raymond
#QQ: 88563128
#Date: 2021-10-09
#FileName: f1.sh
#URL: raymond.blog.csdn.net
#Description: The test script
#Copyright (C): 2021 All rights reserved
#*********************************************************************************************
echo "f1.sh:all args are $@"
echo "f1.sh:all args are $*"
./file.sh "$*"
[root@rocky8 ~]# vim f2.sh
#!/bin/bash
#
#**********************************************************************************************
#Author: Raymond
#QQ: 88563128
#Date: 2021-10-09
#FileName: f2.sh
#URL: raymond.blog.csdn.net
#Description: The test script
#Copyright (C): 2021 All rights reserved
#*********************************************************************************************
echo "f2.sh:all args are $@"
echo "f2.sh:all args are $*"
./file.sh "$@"
[root@rocky8 ~]# vim file.sh
#!/bin/bash
#
#**********************************************************************************************
#Author: Raymond
#QQ: 88563128
#Date: 2021-10-09
#FileName: file.sh
#URL: raymond.blog.csdn.net
#Description: The test script
#Copyright (C): 2021 All rights reserved
#*********************************************************************************************
echo "file.sh:1st arg is $1"
[root@rocky8 ~]# chmod +x f1.sh f2.sh file.sh
[root@rocky8 ~]# ./f1.sh a b c
f1.sh:all args are a b c
f1.sh:all args are a b c
file.sh:1st arg is a b c
[root@rocky8 ~]# ./f2.sh a b c
f2.sh:all args are a b c
f2.sh:all args are a b c
file.sh:1st arg is a
范例: 利用软链接实现同一个脚本不同功能
[root@rocky8 bin]# vim link_test.sh
#!/bin/bash
#
#**********************************************************************************************
#Author: Raymond
#QQ: 88563128
#Date: 2021-10-09
#FileName: link_test.sh
#URL: raymond.blog.csdn.net
#Description: The test script
#Copyright (C): 2021 All rights reserved
#*********************************************************************************************
echo $0
[root@rocky8 bin]# chmod +x link_test.sh
[root@rocky8 bin]# ln -s link_test.sh link_test2.sh
[root@rocky8 bin]# ln -s link_test.sh link_test3.sh
[root@rocky8 bin]# ll link_test*
lrwxrwxrwx 1 root root 12 Oct 9 15:55 link_test2.sh -> link_test.sh
lrwxrwxrwx 1 root root 12 Oct 9 15:56 link_test3.sh -> link_test.sh
-rwxr-xr-x 1 root root 429 Oct 9 15:54 link_test.sh
[root@rocky8 bin]# link_test.sh
/root/bin/link_test.sh
[root@rocky8 bin]# link_test2.sh
/root/bin/link_test2.sh
[root@rocky8 bin]# link_test3.sh
/root/bin/link_test3.sh
#可以把不同脚本创建成不同的软链接,实现不同的效果
2.7.9 退出状态码变量
当我们浏览网页时,有时会看到下图所显示的数字,表示网页的错误信息,我们称为状态码,在shell脚本中也有相似的技术表示程序执行的相应状态。
进程执行后,将使用变量
?
保
存
状
态
码
的
相
关
数
字
,
不
同
的
值
反
应
成
功
或
失
败
,
? 保存状态码的相关数字,不同的值反应成功或失败,
?保存状态码的相关数字,不同的值反应成功或失败,? 取值范例 0-255
$?的值为0 #代表成功
$?的值是1到255 #代表失败
范例:
[root@rocky8 bin]# ping -c1 -W1 hostdown &> /dev/null
[root@rocky8 bin]# echo $?
2
用户可以在脚本中使用以下命令自定义退出状态码
exit [n]
注意:
- 脚本中一旦遇到exit命令,脚本会立即终止;终止退出状态取决于exit命令后面的数字
- 如果未给脚本指定退出状态码,整个脚本的退出状态码取决于脚本中执行的最后一条命令的状态码
范例:
[root@rocky8 bin]# ls
arg.sh f1.sh f2.sh file.sh link_test2.sh link_test3.sh link_test.sh rm.sh
[root@rocky8 bin]# echo $?
0
#$? 执行的是上一个命令的执行状态
[root@rocky8 bin]# xx
-bash: xx: command not found
[root@rocky8 bin]# echo $?
127
[root@rocky8 bin]# ls /app
ls: cannot access '/app': No such file or directory
[root@rocky8 bin]# echo $?
2
#执行结果为0,是成功状态,执行结果为非0,是失败状态
[root@rocky8 bin]# grep -q root /etc/passwd
[root@rocky8 bin]# echo $?
0
[root@rocky8 bin]# grep -q rooter /etc/passwd
[root@rocky8 bin]# echo $?
1
2.7.10 展开命令行
展开命令执行顺序
把命令行分成单个命令词
展开别名
展开大括号的声明{}
展开波浪符声明 ~
命令替换$() 和 ``
再次把命令行分成命令词
展开文件通配*、?、[abc]等等
准备I/0重导向 <、>
运行命令
防止扩展
反斜线(\)会使随后的字符按原意解释
范例:
echo Your cost: \$5.00
Your cost: $5.00
加引号来防止扩展
单引号(’’)防止所有扩展
双引号(”“)也可防止扩展,但是以下情况例外:$(美元符号)
变量扩展
`` : 反引号,命令替换
\:反斜线,禁止单个字符扩展
!:叹号,历史命令替换