第六天
第六天
shell编程语言
面向过程语言
做一件事情,排出个步骤,第一步干什么,第二步干什么,如果出现情况A,做什么处理,如
果出现了情况B,做什么处理
问题规模小,可以步骤化,按部就班处理
以指令为中心,数据服务于指令
C,shell
面向对象语言
将编程看成是一个事物,对外界来说,事物是直接使用的,不用关心事物内部的情况。而编程
就是设置事物能够完成功能。
一种认识世界、分析世界的方法论。将万事万物抽象为各种对象
类是抽象的概念,是万事万物的抽象,是一类事物的共同特征的集合
对象是类的具体实现,是一个实体
问题规模大,复杂系统
以数据为中心,指令服务于数据
java,C#,python,golang等
三种处理逻辑
顺序执行:程序按从上到下顺序执行
选择执行:程序执行过程中,根据条件的不同,进行选择不同分支继续执行
循环执行:程序执行过程中需要重复执行多次某段语句
shell 脚本基本结构
shell脚本编程:是基于过程式、解释执行的语言
编程语言的基本结构:
各种系统命令的组合
数据存储:变量、数组
表达式:a + b
控制语句:if
shell脚本:包含一些命令或声明,并符合一定格式的文本文件
格式要求:首行shebang机制
#!/bin/bash
#!/usr/bin/python
#!/usr/bin/perl
#!/usr/bin/ruby
#!/usr/bin/lua
shell****脚本创建过程
第一步:使用文本编辑器来创建文本文件
第一行必须包括shell声明序列:#!
示例:
#!/bin/bash
添加注释,注释以#开头
第二步:加执行权限
给予执行权限,在命令行上指定脚本的绝对或相对路径
第三步:运行脚本
直接运行解释器,将脚本作为解释器程序的参数运行
shell 脚本注释规范
1、第一行一般为调用使用的语言
2、程序名,避免更改文件名为无法找到正确的文件
3、版本号
4、更改后的时间
5、作者相关信息
6、该程序的作用,及注意事项
7、最后是各版本的更新简要说明
第一个 shell 脚本
[root@centos8 ~]#vim /data/hello.sh
#!/bin/bash
# ------------------------------------------
# Filename: hello.sh
# Version: 1.0
# Date: 2017/06/01
# Author: wang
# Email: 29308620@qq.com
# Website: www.wangxiaochun.com
# Description: This is the first script
# Copyright: 2017 wang
# License: GPL
# ------------------------------------------
#经典写法
echo "hello, world"
#流行写法
echo 'Hello, world!'
#执行方法1
[root@centos8 ~]#bash /data/hello.sh
#执行方法2
[root@centos8 ~]#cat /data/hello.sh | bash
#执行方法3
[root@centos8 ~]#bash < /data/hello.sh
#执行方法4
[root@centos8 ~]#chmod +x /data/hello.sh
#绝对路径
[root@centos8 ~]#/data/hello.sh
#相法路径
[root@centos8 ~]#cd /data/
[root@centos8 ~]#./hello.sh
#执行方法5,本方法可以实现执行远程主机的shell脚本
[root@centos8 ~]#yum -y install httpd
[root@centos8 ~]#systemctl start httpd
[root@centos8 ~]#mv /data/hello.sh /var/www/html/
[root@centos8 ~]#curl http://10.0.0.8/hello.sh
#!/bin/bash
# ------------------------------------------
# Filename: hello.sh
# Version: 1.0
# Date: 2017/06/01
# Author: wang
# Email: 29308620@qq.com
# Website: www.wangxiaochun.com
# Description: This is the first script
# Copyright: 2017 wang
# License: GPL
# ------------------------------------------
#经典写法
echo "hello, world"
#流行写法
echo 'Hello, world!'
[root@centos8 ~]#curl http://10.0.0.8/hello.sh |bash
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 388 100 388 0 0 378k 0 --:--:-- --:--:-- --:--:-- 378k
hello, world
Hello, world!
[root@centos8 ~]#curl -s http://10.0.0.8/hello.sh |bash
hello, world
Hello, world!
[root@centos8 ~]#curl http://10.0.0.8/hello.sh 2>/dev/null |bash
hello, world
Hello, world!
[root@centos8 ~]#curl http://10.0.0.8/hello.sh >/dev/null |bash
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 388 100 388 0 0 378k 0 --:--:-- --:--:-- --:--:-- 378k
[root@centos8 ~]#wget -qO - http://www.wangxiaochun.com/testdir/hello.sh | bash
hello, world
Hello, world!
范例 :备份脚本
#!/bin/bash
#
#********************************************************************
#Author: danian
#QQ: 3078499367
#Date: 2024-02-20
#FileName: backup.sh
#URL: https://www.cnblogs.com/nwq1101
#Description: The test script
#Copyright (C): 2024 All rights reserved
#********************************************************************
echo -e "\033[1;32mStarting backup...\033[0m"
sleep 2
cp -av /etc/ /data/etc`date +%F`/
echo -e "\033[1;32mBackup is finished\033[0m"
shell 脚本调试
只检测脚本中的语法错误,但无法检查出命令错误,但不真正执行脚本
总结:脚本错误常见的有三种
语法错误,会导致后续的命令不继续执行,可以用bash -n 检查错误,提示的出错行数不一定是准
确的
命令错误,默认后续的命令还会继续执行,用bash -n 无法检查出来 ,可以使用 bash -x 进行观察
逻辑错误:只能使用 bash -x 进行观察
变量
变量表示命名的内存空间,将数据放在内存空间中,通过变量名引用,获取数据
变量类型
变量类型:
内置变量,如:PS1,PATH,UID,HOSTNAME,$$,BASHPID,PPID,$?,HISTSIZE
用户自定义变量
不同的变量存放的数据不同,决定了以下
数据存储方式
参与的运算
表示的数据范围
变量数据类型:
字符
数值:整型、浮点型,bash 不支持浮点数
编程语言分类
*静态和动态语言**静态编译语言:使用变量前,先声明变量类型,之后类型不能改变,在编译时检查,如:java,c
动态编译语言:不用事先声明,可随时改变类型,如:bash,Python
**强类型和弱类型语言**
强类型语言:不同类型数据操作,必须经过强制转换才同一类型才能运算,如java , c# ,
python
如:参考以下 python 代码
print('magedu'+ 10) 提示出错,不会自动转换类型
print('magedu'+str(10)) 结果为magedu10,需要显示转换类型
弱类型语言:语言的运行时会隐式做数据类型转换。无须指定类型,默认均为字符型;参与运算会
自动进行隐式类型转换;变量无须事先定义可直接调用
如:bash ,php,javascript
Shell****中变量命名法则
命名要求
区分大小写
不能使程序中的保留字和内置变量:如:if, for
只能使用数字、字母及下划线,且不能以数字开头,注意:不支持短横线 “ - ”,和主机名相反
命名习惯**
见名知义,用英文单词命名,并体现出实际作用,不要用简写,如:ATM
变量名大写
局部变量小写
函数名小写
大驼峰StudentFirstName,由多个单词组成,且每个单词的首字母是大写,其它小写
小驼峰studentFirstName ,由多个单词组成,第一个单词的首字母小写,后续每个单词的首字母是
大写,其它小写
下划线: student_name
变量定义和引用**
变量的生效范围等标准划分变量类型
普通变量:生效范围为当前shell进程;对当前shell之外的其它shell进程,包括当前shell的子shell
进程均无效
环境变量:生效范围为当前shell进程及其子进程
本地变量:生效范围为当前shell进程中某代码片断,通常指函数
弱引用和强引用
"$name" 弱引用,其中的变量引用会被替换为变量值
'$name' 强引用,其中的变量引用不会被替换为变量值,而保持原字符串
范例
[root@centos8 ~]#TITLE='cto'
[root@centos8 ~]#echo $TITLE
cto
[root@centos8 ~]#echo I am $TITLE
I am cto
[root@centos8 ~]#echo "I am $TITLE"
I am cto
[root@centos8 ~]#echo 'I am $TITLE'
I am $TITLE
[root@centos8 ~]#NAME=$USER
[root@centos8 ~]#echo $NAME
root
[root@centos8 ~]#USER=`whoami`
[root@centos8 ~]#echo $USER
root
[root@centos8 ~]#FILE=`ls /run`
[root@centos8 ~]#echo $FILE
agetty.reload atd.pid auditd.pid autofs.fifo-misc autofs.fifo-net console
cron.reboot cryptsetup dbus faillock fsck initctl initramfs lock log mount
NetworkManager plymouth rsyslogd.pid screen sepermit setrans sshd.pid sssd.pid
sudo systemd tmpfiles.d tuned udev user utmp vmware
[root@centos8 ~]#FILE=/etc/*
[root@centos8 ~]#echo $FILE
/etc/adjtime /etc/aliases /etc/alternatives /etc/anacrontab /etc/at.deny
/etc/audit /etc/authselect /etc/autofs.conf /etc/autofs_ldap_auth.conf
[root@centos8 ~]#seq 10
1
2
3
4
5
6
7
8
9
10
[root@centos8 ~]#NUM=`seq 10`
[root@centos8 ~]#echo $NUM
1 2 3 4 5 6 7 8 9 10
[root@centos8 ~]#echo "$NUM"
1
2
3
4
5
6
7
8
9
10
[root@centos8 ~]#NAMES="wang
> zhang
> zhao
> li"
[root@centos8 ~]#echo $NAMES
wang zhang zhao li
[root@centos8 ~]#echo "$NAMES"
wang
zhang
zhao
li
范例:变量引用
[root@centos8 data]#NAME=mage
[root@centos8 data]#AGE=20
[root@centos8 data]#echo $NAME
mage
[root@centos8 data]#echo $AGE
20
[root@centos8 data]#echo $NAME $AGE
mage 20
[root@centos8 data]#echo $NAME$AGE
mage20
[root@centos8 data]#echo $NAME_$AGE
20
[root@centos8 data]#echo ${NAME}_$AGE
mage_20
范例:变量的间接赋值和引用
[root@centos8 ~]#TITLE=cto
[root@centos8 ~]#NAME=wang
[root@centos8 ~]#TITLE=$NAME
[root@centos8 ~]#echo $NAME
wang
[root@centos8 ~]#echo $TITLE
wang
[root@centos8 ~]#NAME=mage
[root@centos8 ~]#echo $NAME
mage
[root@centos8 ~]#echo $TITLE
wang
范例:变量追加值
[root@centos8 ~]#TITLE=CTO
[root@centos8 ~]#TITLE+=:wang
[root@centos8 ~]#echo $TITLE
CTO:wang
范例:利用变量实现动态命令
[root@centos8 ~]#CMD=hostname
[root@centos8 ~]#$CMD
centos8.wangxiaochun.com
显示已定义的所有变量:
set
删除变量:
unset <name>
范例:
[root@centos8 ~]#NAME=mage
[root@centos8 ~]#TITLE=ceo
[root@centos8 ~]#echo $NAME $TITLE
mage ceo
[root@centos8 ~]#unset NAME TITLE
[root@centos8 ~]#echo $NAME $TITLE
范例:显示系统信息
[root@centos8 scripts]#cat systeminfo.sh
#!/bin/bash
#
#********************************************************************
#Author: wangxiaochun
#QQ: 29308620
#Date: 2019-12-23
#FileName: systeminfo.sh
#URL: http://www.magedu.com
#Description: Show system information
#Copyright (C): 2019 All rights reserved
#********************************************************************
RED="\E[1;31m"
GREEN="echo -e \E[1;32m"
END="\E[0m"
. /etc/os-release
$GREEN----------------------Host systeminfo--------------------$END
echo -e "HOSTNAME: $RED`hostname`$END"
#echo -e "IPADDR: $RED` ifconfig eth0|grep -Eo '([0-9]{1,3}\.){3}[0-9]
{1,3}' |head -n1`$END"
echo -e "IPADDR: $RED` hostname -I`$END"
echo -e "OSVERSION: $RED$PRETTY_NAME$END"
echo -e "KERNEL: $RED`uname -r`$END"
echo -e "CPU: $RED`lscpu|grep '^Model name'|tr -s ' '|cut -d : -
f2`$END"
echo -e "MEMORY: $RED`free -h|grep Mem|tr -s ' ' : |cut -d : -f2`$END"
echo -e "DISK: $RED`lsblk |grep '^sd' |tr -s ' ' |cut -d " " -f4`$END"
$GREEN---------------------------------------------------------$END
[root@centos8 scripts]#cat system_info.sh
#!/bin/bash
#
#********************************************************************
#Author: wangxiaochun
#QQ: 29308620
#Date: 2019-12-23
#FileName: systeminfo.sh
#URL: http://www.magedu.com
#Description: Show system information
#Copyright (C): 2019 All rights reserved
#********************************************************************
RED="\E[1;31m"
GREEN="echo -e \E[1;32m"
END="\E[0m"
$GREEN----------------------Host systeminfo--------------------$END
echo -e "HOSTNAME: $RED`hostname`$END"
echo -e "IPADDR: $RED` ifconfig eth0|grep -Eo '([0-9]{1,3}\.){3}[0-9]
{1,3}' |head -n1`$END"
echo -e "OSVERSION: $RED`cat /etc/redhat-release`$END"
echo -e "KERNEL: $RED`uname -r`$END"
echo -e "CPU: $RED`lscpu|grep 'Model name'|tr -s ' '|cut -d : -f2`$END"
echo -e "MEMORY: $RED`free -h|grep Mem|tr -s ' ' : |cut -d : -f2`$END"
echo -e "DISK: $RED`lsblk |grep '^sd' |tr -s ' ' |cut -d " " -f4`$END"
$GREEN---------------------------------------------------------$END
范例
[root@centos8 script]#cat backup.sh
#!/bin/bash
#Author: wang
#Date: 2020-08-05
#Description: test
#FILE: backup.sh
#VERSION: 1.0
COLOR='echo -e \E[1;35m'
END='\E[0m'
BACKUP=/backup
SRC=/etc
DATE=`date +%F`
${COLOR}Starting backup...$END
sleep 2
cp -av $SRC ${BACKUP}${SRC}_$DATE
${COLOR}Backup is finished$END
环境变量
环境变量:
可以使子进程(包括孙子进程)继承父进程的变量,但是无法让父进程使用子进程的变量
一旦子进程修改从父进程继承的变量,将会新的值传递给孙子进程
一般只在系统配置文件中使用,在脚本中较少使用
变量声明和赋值:
#声明并赋值
export name=VALUE
declare -x name=VALUE
\#或者分两步实现
name=VALUE
export name
变量引用:
$name
${name}
显示所有环境变量:
env
printenv
export
declare -x
查看指定进程的环境变量
cat /proc/$PID/environ
删除变量:
unset name
bash内建的环境变量
PATH
SHELL
USER
UID
HOME
PWD
SHLVL #shell的嵌套层数,即深度
LANG
MAIL
HOSTNAME
HISTSIZE
_ #下划线,表示前一命令的最后一个参数
范例
查看进程的环境变量
[root@centos8 ~]#cat /proc/1235/environ
USER=rootLOGNAME=rootHOME=/rootPATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/us
r/binSHELL=/bin/bashTERM=linuxSSH_AUTH_SOCK=/tmp/sshiIeuAxdLiY/agent.1234XDG_SESSION_ID=1XDG_RUNTIME_DIR=/run/user/0DBUS_SESSION_BUS
_ADDRESS=unix:path=/run/user/0/busSSH_CLIENT=10.0.0.1 13258
22SSH_CONNECTION=10.0.0.1 13258 10.0.0.8 22SSH_TTY=/dev/pts/0[root@centos8 ~]#
[root@centos8 ~]#
[root@centos8 ~]#cat /proc/1235/environ |tr '\0' '\n'
USER=root
LOGNAME=root
HOME=/root
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin
SHELL=/bin/bash
TERM=linux
SSH_AUTH_SOCK=/tmp/ssh-iIeuAxdLiY/agent.1234
XDG_SESSION_ID=1
XDG_RUNTIME_DIR=/run/user/0
DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/0/bus
SSH_CLIENT=10.0.0.1 13258 22
SSH_CONNECTION=10.0.0.1 13258 10.0.0.8 22
SSH_TTY=/dev/pts/0
只读变量
定义:只能声明定义,但后续不能修改和删除,即常量
声明只读变量
readonly name
declare -r name
查看只读变量
readonly [-p]
declare -r
范例
root@ubuntu2204:~# readonly PI=3.14159
root@ubuntu2204:~# echo $PI
3.14159
root@ubuntu2204:~# PI=3.14
-bash: PI: readonly variable
root@ubuntu2204:~# unset PI
-bash: unset: PI: cannot unset: readonly variable
root@ubuntu2204:~# echo $PI
3.14159
root@ubuntu2204:~# exit
logout
Connection closing...Socket close.
Connection closed by foreign host.
Disconnected from remote host(Ubuntu2204(root)) at 19:17:37.
Type `help' to learn how to use Xshell prompt.
[C:\~]$
位置变量
定义:在bash shell中内置的变量, 在脚本代码中调用通过命令行传递给脚本的参数
$1, $2, ... 对应第1个、第2个等参数,shift [n]换位置
$0 命令本身,包括路径
$* 传递给脚本的所有参数,全部参数合为一个字符串
$@ 传递给脚本的所有参数,每个参数为独立字符串
$# 传递给脚本的参数的个数
注意:$@ $* 只在被双引号包起来的时候才会有差异
清空所有位置变量
set --
范例
[root@centos8 ~]#cat /data/scripts/arg.sh
#!/bin/bash
#
#********************************************************************
#Author: wangxiaochun
#QQ: 29308620
#Date: 2020-04-01
#FileName: arg.sh
#URL: http://www.magedu.com
#Description: The test script
#Copyright (C): 2020 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 "The number of arg is $#"
echo "All args are $*"
echo "All args are $@"
echo "The scriptname is `basename $0`"
[root@centos8 ~]#bash /data/scripts/arg.sh {a..z}
1st arg is a
2st arg is b
3st arg is c
10st arg is j
11st arg is k
The number of arg is 26
All args are 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 args are 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
The scriptname is arg.sh
范例
删库跑路之命令rm的安全实现
[root@centos8 ~]#cat /data/scripts/rm.sh
#!/bin/bash#
#********************************************************************
#Author: wangxiaochun
#QQ: 29308620
#Date: 2020-04-01
#FileName: rm.sh
#URL: http://www.magedu.com
#Description: The test script
#Copyright (C): 2020 All rights reserved
#********************************************************************
WARNING_COLOR="echo -e \E[1;31m"
END="\E[0m"
DIR=/tmp/`date +%F_%H-%M-%S`
mkdir $DIR
mv $* $DIR
${WARNING_COLOR}Move $* to $DIR $END
[root@centos8 ~]#chmod a+x /data/scripts/rm.sh
[root@centos8 ~]#alias rm='/data/scripts/rm.sh'
[root@centos8 ~]#touch {1..10}.txt
[root@centos8 ~]#rm *.txt
Move 10.txt 1.txt 2.txt 3.txt 4.txt 5.txt 6.txt 7.txt 8.txt 9.txt to /tmp/2020-
04-01_15-15-28
范例:$*和$@的区别
[root@centos8 scripts]#cat f1.sh
#!/bin/bash
echo "f1.sh:all args are $@"
echo "f1.sh:all args are $*"
./file.sh "$*"
[root@centos8 scripts]#cat f2.sh
#!/bin/bash
echo "f2.sh:all args are $@"
echo "f2.sh:all args are $*"
./file.sh "$@"
[root@centos8 scripts]#cat file.sh
#!/bin/bash
echo "file.sh:1st arg is $1"
[root@centos8 scripts]#./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@centos8 scripts]#./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@centos8 ~]#cat test.sh
#!/bin/bash
#********************************************************************
echo $0
[root@centos8 ~]#ln -s test.sh a.sh
[root@centos8 ~]#ln -s test.sh b.sh
[root@centos8 ~]#./a.sh
./a.sh
[root@centos8 ~]#./b.sh
./b.sh
退出状态码变量
当我们浏览网页时,有时会看到下图所显示的数字,表示网页的错误信息,我们称为状态码,在shell脚
本中也有相似的技术表示程序执行的相应状态。
进程执行后,将使用变量 $? 保存状态码的相关数字,不同的值反应成功或失败,$?取值范例 0-255
$?的值为0 #代表成功
$?的值是1到255 #代表失败
范例
ping -c1 -w1 hostdown &> /dev/null
[root@centos8 ~]#curl -fs http://www.wangxiaochun.com >/dev/null
[root@centos8 ~]#echo $?
0
exit [n]
注意:
脚本中一旦遇到exit命令,脚本会立即终止;终止退出状态取决于exit命令后面的数字
如果exit后面无数字,终止退出状态取决于exit命令前面命令执行结果
如果没有exit命令, 即未给脚本指定退出状态码,整个脚本的退出状态码取决于脚本中执行的最后
一条命令的状态码
展开命令行
把命令行分成单个命令词
展开别名
展开大括号的声明{}
展开波浪符声明 ~
命令替换$() 和 ``
再次把命令行分成命令词
展开文件通配符*、?、[abc]等等
准备I/0重导向 <、>
运行命令
反斜线(\)会使随后的字符按原意解释
j加括号来防止扩展
单引号(’’)防止所有扩展
双引号(”“)也可防止扩展,但是以下情况例外:$(美元符号)
变量扩展
`` : 反引号,命令替换
\:反斜线,禁止单个字符扩展
!:叹号,历史命令替换
范例
``和$() 区别
[root@centos8 ~]#echo `echo \`
\> ^C
[root@centos8 ~]#echo `echo \\`
[root@centos8 ~]#echo `echo \\\`
\> ^C
[root@centos8 ~]#echo `echo \\\\`
\
[root@centos8 ~]#echo $(echo \)
\> ^C
[root@centos8 ~]#echo $(echo \\)
\
[root@centos8 ~]#echo $(echo \\\)
\> ^C
[root@centos8 ~]#echo $(echo \\\\)
\\
脚本安全和 set
set 命令:可以用来定制 shell 环境
$- 变量
h:hashall,打开选项后,Shell 会将命令所在的路径hash下来,避免每次都要查询。通过set +h将h选
项关闭
i:interactive-comments,包含这个选项说明当前的 shell 是一个交互式的 shell。所谓的交互式shell,
在脚本中,i选项是关闭的
m:monitor,打开监控模式,就可以通过Job control来控制进程的停止、继续,后台或者前台执行等
B:braceexpand,大括号扩展
H:history,H选项打开,可以展开历史列表中的命令,可以通过!感叹号来完成,例如“!!”返回上最近的
一个历史命令,“!n”返回第 n 个历史命令
范例:
[root@centos8 ~]#echo $-
himBHs
[root@centos8 ~]#set +h
[root@centos8 ~]#echo $-
imBHs
[root@centos8 ~]#hash
-bash: hash: hashing disabled
[root@centos8 ~]#echo {1..10}
1 2 3 4 5 6 7 8 9 10
[root@centos8 ~]#echo $-
imBHs
[root@centos8 ~]#set +B
[root@centos8 ~]#echo $-
imHs
[root@centos8 ~]#echo {1..10}
{1..10}
set 命令实现脚本安全
-u 在扩展一个没有设置的变量时,显示错误信息, 等同set -o nounset
-e 如果一个命令返回一个非0退出状态值(失败)就退出, 等同set -o errexit
-o option 显示,打开或者关闭选项
显示选项:set -o
打开选项:set -o 选项
关闭选项:set +o 选项
-x 当执行命令时,打印命令及其参数,类似 bash -x
范例:
[root@centos8 ~]#set -o
allexport off
braceexpand on
emacs on
errexit off
errtrace off
functrace off
hashall on
histexpand on
history on
ignoreeof off
interactive-comments on
keyword off
monitor on
noclobber off
noexec off
noglob off
nolog off
notify off
nounset off
onecmd off
physical off
pipefail off
posix off
privileged off
verbose off
vi off
xtrace off
范例
DIR=/data
cd $DIR
rm -rf *
#rm -rf $DIr/*
格式化输出 printf
相当于增强版的 echo, 实现丰富的格式化输出
**常用格式替换符**
printf "指定的格式" "文本1" ”文本2“……**替换**
**符** **功能**
%s 字符串
%d,%i 十进制整数
%f 浮点格式
%c ASCII字符,即显示对应参数的第一个字符
%b 相对应的参数中包含转义字符时,可以使用此替换符进行替换,对应的转义字符会被转义
%o 八进制值
%u 不带正负号的十进制值
%x 十六进制值(a-f)
%X 十六进制值(A-F)
%% 表示%本身
说明
%#s 中的数字代表此替换符中的输出字符宽度,不足补空格,默认是右对齐,%-10s表示10个字符宽,- 表示
左对齐
%03d 表示3位宽度,不足前面用0补全,超出位数原样输出
%.2f 中的2表示小数点后显示的小数位数
常用转义字符
转义符 功能
\a 警告字符,通常为ASCII的BEL字符
\b 后退
\f 换页
\n 换行
\r 回车
\t 水平制表符
\v 垂直制表符
\ 表示\本身
范例
[root@centos8 ~]#printf "%s" 1 2 3 4
1234[root@centos8 ~]#
[root@centos8 ~]#printf "%s\n" 1 2 3 4
1
2
3
4
[root@centos8 ~]#printf "%f\n" 1 2 3 4
1.000000
2.000000
3.000000
4.000000
#.2f 表示保留两位小数
[root@centos8 ~]#printf "%.2f\n" 1 2 3 4
1.00
2.00
3.00
4.00
[root@centos8 ~]#printf "(%s)" 1 2 3 4;echo
(1)(2)(3)(4)
[root@centos8 ~]#printf " (%s) " 1 2 3 4;echo ""
(1) (2) (3) (4)
[root@centos8 ~]#printf "(%s)\n" 1 2 3 4
(1)
(2)
(3)
(4)
[root@centos8 ~]#printf "%s %s\n" 1 2 3 4
1 2
3 4
[root@centos8 ~]#printf "%s %s %s\n" 1 2 3 4
1 2 3
4
#%-10s 表示宽度10个字符,左对齐
[root@centos8 ~]#printf "%-10s %-10s %-4s %s \n" 姓名 性别 年龄 体重 小明 男 20 70
小红 女 18 50
姓名 性别 年龄 体重
小明 男 20 70
小红 女 18 50
#将十进制的17转换成16进制数
[root@centos8 ~]#printf "%X" 17
11[root@centos8 ~]#
#将十六进制C转换成十进制
[root@centos8 ~]#printf "%d\n" 0xC
12
[root@rocky8 ~]#VAR="welcome to Magedu";printf "\033[1;32m%s\033[0m " $VAR
welcome to Magedu
[root@centos8 ~]#VAR="welcome to Magedu";printf "\033[1;32m%s\033[0m\n" $VAR
welcome
to
Magedu
[root@centos8 ~]#VAR="welcome to Magedu";printf "\033[1;32m%s\033[0m\n" "$VAR"
welcome to Magedu
算术运算
Shell允许在某些情况下对算术表达式进行求值,比如:let和declare 内置命令,(( ))复合命令和算术扩
展。求值以固定宽度的整数进行,不检查溢出,尽管除以0 被困并标记为错误。运算符及其优先级,关
联性和值与C语言相同。以下运算符列表分组为等优先级运算符级别。级别按降序排列优先。
注意:****bash 只支持整数,不支持小数
+ - addition, subtraction
* / % multiplication, division, remainder, %表示取模,即取余数,示例:9%4=1,5%3=2
i++ i-- variable post-increment and post-decrement
++i --i variable pre-increment and pre-decrement
= *= /= %= += -= <<= >>= &= ^= |= assignment
- + unary minus and plus
! ~ logical and bitwise negation
** exponentiation 乘方,即指数运算
<< >> left and right bitwise shifts
<= >= < > comparison
== != equality and inequality
& bitwise AND
| bitwise OR
^ bitwise exclusive OR
&& logical AND
|| logical OR
expr?expr:expr conditional operator
expr1 , expr2 comma
乘法符号有些场景中需要转义
实现算术运算:
(1) let var=算术表达式
(2) ((var=算术表达式)) 和上面等价
(3) var=$[算术表达式]
(4) var=$((算术表达式))
(5) var=$(expr arg1 arg2 arg3 ...)
(6) declare -i var = 数值
(7) echo '算术表达式' | bc
内建的随机数生成器变量
$RANDOM 取值范围:0-32767
范例
\#生成 0 - 49 之间随机数
echo $[$RANDOM%50]
\#随机字体颜色
[root@centos8 ~]#echo -e "\033[1;$[RANDOM%7+31]mhello\033[0m"
magedu
增强型赋值
+= i+=10 相当于 i=i+10
-= i-=j 相当于 i=i-j
*=
/=
%=
++ i++,++i 相当于 i=i+1
-- i--,--i 相当于 i=i-1
格式
let varOPERvalue
范例
[root@centos8 ~]#let i=10*2
[root@centos8 ~]#echo $i
20
[root@centos8 ~]#((j=i+10))
[root@centos8 ~]#echo $j
30
范例
\#自加3后自赋值
let count+=3
[root@centos8 ~]#i=10
[root@centos8 ~]#let i+=20 #相当于let i=i+20
[root@centos8 ~]#echo $i
30
[root@centos8 ~]#j=20
[root@centos8 ~]#let i*=j
[root@centos8 ~]#echo $i
600
范例
#自增,自减
let var+=1
let var++
let var-=1
let var--
[root@centos8 ~]#unset i j ; i=1; let j=i++; echo "i=$i,j=$j"
i=2,j=1
[root@centos8 ~]#unset i j ; i=1; let j=++i; echo "i=$i,j=$j"
i=2,j=2
[root@centos8 ~]#expr 2 * 3
expr: syntax error: unexpected argument ‘anaconda-ks.cfg’
[root@centos8 ~]#ls
anaconda-ks.cfg
[root@centos8 ~]#expr 2 \* 3
6
[root@centos8 ~]#echo "scale=3;20/3"|bc
6.666
[root@centos8 ~]#i=10
[root@centos8 ~]#j=20
[root@centos8 ~]#declare -i result=i*j
[root@centos8 ~]#echo $result
200
范例:鸡兔同笼,是中国古代著名典型趣题之一,记载于《孙子算经》之中。今有雉兔同笼,上有三十
五头,下有九十四足,问雉兔各几何?
#!/bin/bash
#
#********************************************************************
#Author: wangxiaochun
#QQ: 29308620
#Date: 2021-12-17
#FileName: /data/scripts/chook_rabbit.sh
#URL: http://www.wangxiaochun.com
#Description: The test script
#Copyright (C): 2021 All rights reserved
#********************************************************************
HEAD=$1
FOOT=$2
RABBIT=$(((FOOT-HEAD-HEAD)/2))
CHOOK=$[HEAD-RABBIT]
echo RABBIT:$RABBIT
echo CHOOK:$CHOOK
逻辑运算
或与非
1,真
0,假
\#注意,以上为二进制
与:****& 和0相与结果为0,和1相与结果保留原值, 一假则假,全真才真
0 与 0 = 0
0 与 1 = 0
1 与 0 = 0
1 与 1 = 1
范例
[root@ubuntu1804 ~]#x=$[2&6]
[root@ubuntu1804 ~]#echo $x
2
[root@ubuntu1804 ~]#x=$[7&3]
[root@ubuntu1804 ~]#echo $x
3
或:****| 和1相或结果为1,和0相或结果保留原值,一真则真,全假才假
0 或 0 = 0
0 或 1 = 1
1 或 0 = 1
1 或 1 = 1
范例
[root@ubuntu1804 ~]#echo $x
7
[root@ubuntu1804 ~]#x=$[2|5]
[root@ubuntu1804 ~]#echo $x
7
非:!
! 1 = 0 ! true
! 0 = 1 ! false
异或:****^
异或的两个值,相同为假,不同为真。两个数字X,Y异或得到结果Z,Z再和任意两者之一X异或,将得出
另一个值Y
0 ^ 0 = 0
0 ^ 1 = 1
1 ^ 0 = 1
1 ^ 1 = 0
范例
[root@centos8 ~]#true
[root@centos8 ~]#echo $?
0
[root@centos8 ~]#false
[root@centos8 ~]#echo $?
1
[root@centos8 ~]#! true
[root@centos8 ~]#echo $?
1
[root@centos8 ~]#! false
[root@centos8 ~]#echo $?
0
范例: 变量互换
[root@centos8 ~]#x=10;y=20;temp=$x;x=$y;y=$temp;echo x=$x,y=$y
x=20,y=10
[root@centos8 ~]#x=10;y=20;x=$[x^y];y=$[x^y];x=$[x^y];echo x=$x,y=$y
x=20,y=10
短路运算
短路与 &&
CMD1 && CMD2
第一个CMD1结果为真(1),第二个CMD2必须要参与运算,才能得到最终的结果
第一个CMD1结果为假(0),总的结果必定为0,因此不需要执行CMD2
短路||
CMD1 || CMD2
第一个CMD1结果为真(1),总的结果必定为1,因此不需要执行CMD2
第一个CMD1结果为假(0),第二个CMD2 必须要参与运算,才能得到最终的结果
短路与和或组合
CMD1 && CMD2 || CMD3
当CMD1执行成功时,会执行CMD2
当CMD1执行失败时,会执行CMD3
注意: CMD1 || CMD2 && CMD3 逻辑不通,不使用
条件测试命令
条件测试:判断某需求是否满足,需要由测试机制来实现,专用的测试表达式需要由测试命令辅助完成
测试过程,实现评估布尔声明,以便用在条件性环境下进行执行
若真,则状态码变量 $? 返回0
若假,则状态码变量 $? 返回1
条件测试命令
test EXPRESSION
[ EXPRESSION ] #和test 等价,建议使用 [ ]
[[ EXPRESSION ]] 相关于增强版的 [ ], 支持[]的用法,且支持扩展正则表达式和通配符
注意:EXPRESSION前后必须有空白字符
重点
shell脚本格式
shebang机制#!/bin/bash
变量
普通变量
环境变量
只读变量
位置变量--$1,$2,$#,$*,$@, $0
状态--$?
条件测试
【】 test
[[=~]]---功能更强
文件
数字
字符串
逻辑处理
与或非
短路
&&
||
配置文件
/etc/bashrc
~/.bashrc
read
条件分支
if
case
循环
for