07-SHELL编程基础

目录

1 shell脚本的基本用法

1.1 shell脚本的用途

1.2 shell脚本的注释规范

1.3 第一个shell脚本

1.4 shell脚本调试

1.5 变量

1.5.1 变量的类型

1.5.2 变量的命令规则

1.5.3 变量的定义与使用

1.5.4 环境变量

1.5.5 只读变量

1.5.6 位置变量

1.5.7 退出状态码变量

1.5.8 脚本安全和set

1.6 格式化输出print

1.7 算数运算

1.8 条件测试命令

1.8.1 变量测试

1.8.2 数值测试

1.8.3 字符串测试

1.8.4 文件测试

1.8.5 关于()和{}

1.8.6 短路与或非

1.9 使用read命令来接受输入

2 bash配置文件

2.1 按生效范围划分两类

2.2 按功能划分

2.3 配置文件生效

2.4 Bash 退出任务

3 流程控制之条件选择

3.1 选择执行 if 语句

3.2 条件判断case语句


1 shell脚本的基本用法

1.1 shell脚本的用途

  • 自动化常用命令
  • 执行系统管理和故障排除
  • 创建简单的应用程序
  • 处理文本或文件

1.2 shell脚本的注释规范

  1. 第一行一般为调用使用的语言
  2. 程序名,避免更改文件名为无法找到正确的文件
  3. 版本号
  4. 更改后的时间
  5. 作者相关信息
  6. 该程序的作用,及注意事项
  7. 最后是各版本的更新简要说明

1.3 第一个shell脚本

范例:第一个shell脚本hello word

脚本执行方法:

执行远程主机脚本:

curl -s http://10.0.0.100/hello.sh|bash

wget -qO - http://10.0.0.100/testdir/hello.sh  |bash

备份脚本:

1.4 shell脚本调试

只检测脚本中的语法错误,但无法检查出命令错误,但不真正执行脚本

bash -n script.sh

调试并执行,常用于检查脚本中的命令错误

bash -x

脚本中常见的三种错误:

  • 语法错误,会导致后续的命令不继续执行,可以用bash -n 检查错误,提示的出错行数不一定是准确的。
  • 命令错误,默认后续的命令还会继续执行,用bash -n 无法检查出来 ,可以使用 bash -x 进行观察。
  • 逻辑错误:只能使用 bash -x 进行观察。

1.5 变量

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

1.5.1 变量的类型

变量有两种类型:

  • 内置变量:PS1,PATH,UID,HOSTNAME等
  • 用户自定义变量

变量的数据类型:

  • 字符
  • 数值:整型、浮点型,bash 不支持浮点数

1.5.2 变量的命令规则

  • 不能使程序中的保留字:如:if, for
  • 只能使用数字、字母及下划线,且不能以数字开头,注意:不支持短横线 “ - ”,和主机名相反
  • 见名知义,用英文单词命名,并体现出实际作用,不要用简写,如:ATM
  • 统一命名规则:驼峰命名法, studentname,大驼峰StudentName 小驼峰studentName
  • 变量名大写:STUDENT_NAME
  • 局部变量小写
  • 函数名小写

1.5.3 变量的定义与使用

变量的生效范围等标准划分变量类型:

  • 普通变量:生效范围为当前shell进程;对当前shell之外的其它shell进程,包括当前shell的子shell进程均无效
  • 环境变量:生效范围为当前shell进程及其子进程
  • 本地变量:生效范围为当前shell进程中某代码片断,通常指函数

变量的赋值:

name='value'

value 可以是以下多种形式:

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

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

变量的引用:

$name
${name}

弱引用和强引用:

  • "$name " 弱引用,其中的变量引用会被替换为变量值
  • '$name ' 强引用,其中的变量引用不会被替换为变量值,而保持原字符串

范例:变量追加值

范例:利用变量实现动态命令

显示已定义的所有变量

set

删除变量

unset <name>

范例:显示系统信息的脚本

#!/bin/bash
# ------------------------------------------
# Filename: hello.sh
# Version: 1.0
# Date: 202024/06/23
# Author: yang
# Email: 123456@qq.com
# Website: www.baidu.com
# Description: This is the first script
# Copyright: 2024 yang
# License: GPL
# ------------------------------------------
RED="\E[1;31m"
GREEN="\E[1;32m"
END="\E[0m"
echo -e "$GREEN----------------------Host systeminfo--------------------$END"
echo -e "HOSTNAME: $RED`hostname`$END"
echo -e "IPADDR: $RED` ifconfig ens33|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"
echo -e "$GREEN---------------------------------------------------------$END"

1.5.4 环境变量

环境变量说明:

  • 可以使子进程继承父进程的变量,但是无法让父进程使用子进程的变量
  • 一般只在系统配置文件中使用,在脚本中较少使用

变量声明和赋值:

#声明并赋值
export name=VALUE
declare -x name=VALUE

#或者分两步实现
name=VALUE
export name

显示所有的环境变量:

env
printenv
export
declare -x

常见的bash内置环境变量:

PATH
SHELL
USER
UID
HOME
PWD
SHLVL #shell的嵌套层数,即深度
LANG
MAIL
HOSTNAME
HISTSIZE
_ #下划线 表示前一命令的最后一个参数

1.5.5 只读变量

只读变量:只能声明定义,但后续不能修改和删除,即常量

声明只读变量:

readonly name
declare  -r name

查看只读变量:

readonly  [-p]
declare -r

1.5.6 位置变量

位置变量:在bash shell中内置的变量, 在脚本代码中调用通过命令行传递给脚本的参数

$1, $2, ... 对应第1个、第2个等参数,shift [n]换位置
$0   命令本身,包括路径
$*   传递给脚本的所有参数,全部参数合为一个字符串
$@   传递给脚本的所有参数,每个参数为独立字符串
$#   传递给脚本的参数的个数
注意:$@ $* 只在被双引号包起来的时候才会有差异

清空所有位置变量:

set --

范例:rm命令的安全实现

#!/bin/bash
# ------------------------------------------
# Filename: hello.sh
# Version: 1.0
# Date: 202024/06/23
# Author: yang
# Email: 123456@qq.com
# Website: www.baidu.com
# Description: This is the first script
# Copyright: 2024 wang
# License: GPL
# ------------------------------------------
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

1.5.7 退出状态码变量

进程执行后,将使用变量 $? 保存状态码的相关数字,不同的值反应成功或失败,$?取值范例 0-255。

$?的值为0          #代表成功
$?的值是1到255     #代表失败

范例:

用户可以在脚本中使用以下命令自定义退出状态码:

exit [n]

注意:

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

1.5.8 脚本安全和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 个历史命令

 

set 命令实现脚本安全

  • -u 在扩展一个没有设置的变量时,显示错误信息, 等同set -o nounset
  • -e 如果一个命令返回一个非0退出状态值(失败)就退出, 等同set -o errexit
  • -o option 显示,打开或者关闭选项
    • 显示选项:set -o
    • 打开选项:set -o 选项
    • 关闭选项:set +o 选项
  • -x 当执行命令时,打印命令及其参数,类似 bash -x

1.6 格式化输出print

格式:

printf "指定的格式" "文本1" ”文本2“……

常用格式替换符: 

替换符功能
%s字符串
%f 浮点格式
%b相对应的参数中包含转义字符时,可以使用此替换符进行替换,对应的转义字符会被转 义
%cASCII字符,即显示对应参数的第一个字符
%d,%i十进制整数
%o八进制值
%u不带正负号的十进制整数
%x十六进制值(a-f)
%X十六进制值(A-F)
%%表示%本身

常用转义字符:

1.7 算数运算

shell 支持算术运算,但只支持整数,不支持小数

bash中的算术运算:

  • +
  • -
  • *
  • /
  • % 取模,即取余数,示例:9%4=1,5%3=2
  • ** 乘方

实现算术运算:

(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的随机数和生成随机颜色的字符串

增强型赋值:

+=  i+=10  相当于 i=i+10-=  i-=j   
相当于 i=i-j
 *=
 /=
 %=
 ++  i++,++i    --  i--,--i    
相当于 i=i+1
相当于 i=i-1

1.8 条件测试命令

条件测试:判断某需求是否满足,需要由测试机制来实现,专用的测试表达式需要由测试命令辅助完成测试过程,若条件真,则状态码变量 $? 返回0 若假,则状态码变量 $? 返回。

条件测试命令

  • test EXPRESSION
  • [ EXPRESSION ] #和test 等价,建议使用 [ ]
  • [[ EXPRESSION ]]
  • 注意:EXPRESSION前后必须有空白字符

1.8.1 变量测试

#判断 NAME 变量是否定义
[ -v NAME ] 
#判断 NAME 变量是否定义并且是名称引用,bash 4.4新特性
[ -R NAME ]

1.8.2 数值测试

-eq 是否等于
-ne 是否不等于
-gt 是否大于
-ge 是否大于等于
-lt 是否小于
-le 是否小

1.8.3 字符串测试

test 和 [ ] 用法
-z 字符串是否为空,没定义或空为真,不空为假
-n 字符串是否不空,不空为真,空为假

STRING1 = STRING2   是否等于,注意 = 前后有空格
STRING1 != STRING2  是否不等于
>   ascii码是否大于ascii码
<   是否小于

[[]] 用法,建议,当使用正则表达式或通配符使用,一般情况使用 [ ]
 ==  左侧字符串是否和右侧的PATTERN相同
	注意:此表达式用于[[  ]]中,PATTERN为通配符
=~  左侧字符串是否能够被右侧的正则表达式的PATTERN所匹配
	注意: 此表达式用于[[ ]]中;扩展的正则表达式

1.8.4 文件测试

文件存在性测试:

-a FILE:同 -e
-e FILE: 文件存在性测试,存在为真,否则为假
-b FILE:是否存在且为块设备文件
-c FILE:是否存在且为字符设备文件
-d FILE:是否存在且为目录文件
-f FILE:是否存在且为普通文件
-h FILE 或 -L FILE:存在且为符号链接文件
-p FILE:是否存在且为命名管道文件
-S FILE:是否存在且为套接字文件

文件权限测试:

-r FILE:是否存在且可读
-w FILE: 是否存在且可写
-x FILE: 是否存在且可执行
-u FILE:是否存在且拥有suid权限
-g FILE:是否存在且拥有sgid权限
-k FILE:是否存在且拥有sticky权限

注意:最终结果由用户对文件的实际权限决定,而非文件属性决定

文件属性测试:

-s FILE #是否存在且非空
-t fd #fd 文件描述符是否在某终端已经打开
-N FILE #文件自从上一次被读取之后是否被修改过
-O FILE #当前有效用户是否为文件属主
-G FILE #当前有效用户是否为文件属组
FILE1 -ef FILE2 #FILE1是否是FILE2的硬链接
FILE1 -nt FILE2 #FILE1是否新于FILE2(mtime)
FILE1 -ot FILE2 #FILE1是否旧于FILE2

1.8.5 关于()和{}

(CMD1;CMD2;...)和 { CMD1;CMD2;...; } 都可以将多个命令组合在一起,批量执行

  • ( list ) 会开启子shell,并且list中变量赋值及内部命令执行后,将不再影响后续的环境, 帮助参看:man bash 搜索(list)
  • { list; } 不会启子shell, 在当前shell中运行,会影响当前shell环境, 帮助参看:man bash 搜索{ list;

1.8.6 短路与或非

COMMAND1 && COMMAND2    #并且,短路与,代表条件性的AND  THEN
如果COMMAND1 成功,将执行COMMAND2,否则,将不执行COMMAND2

COMMAND1 || COMMAND2    #或者,短路或,代表条件性的OR  ELSE
如果COMMAND1 成功,将不执行COMMAND2,否则,将执行COMMAND2

! COMMAND               #非,取反

COMMAND1 && COMMAND2 || COMMAND3
如果 COMMAND1 成功 执行 COMMAND2 反之执行 COMMAND3

1.9 使用read命令来接受输入

使用read来把输入值分配给一个或多个shell变量,read从标准输入中读取值,给每个单词分配一个变 量,所有剩余单词都被分配给最后一个变量,如果变量名没有指定,默认标准输入的值赋值给系统内置 变量REPLY。

常见选项:

  • -p 指定要显示的提示
  • -s 静默输入,一般用于密码
  • -n N 指定输入的字符长度N
  • -d '字符' 输入结束符
  • -t N TIMEOUT为N秒

范例: read和输入重定向

2 bash配置文件

2.1 按生效范围划分两类

全局配置:

/etc/profile
/etc/profile.d/*.sh
/etc/bashrc

个人配置:

~/.bash_profile
~/.bashrc

2.2 按功能划分

profile类为交互式登录的shell提供配置

全局:/etc/profile, /etc/profile.d/*.sh
个人:~/.bash_profile

功能:

  1. 用于定义环境变量
  2. 运行命令或脚本

bashrc类:为非交互式和交互式登录的shell提供配置

全局:/etc/bashrc
个人:~/.bashrc

功能: 

  1. 定义命令别名和函数
  2. 定义本地变量

2.3 配置文件生效

修改profile和bashrc文件后需生效两种方法:

  1. 重新启动shell进程
  2. source | . 配置文件

2.4 Bash 退出任务

保存在~/.bash_logout文件中(用户),在退出登录shell时运行

功能:

  1. 创建自动备份
  2. 清除临时文件

3 流程控制之条件选择

3.1 选择执行 if 语句

格式:

if 判断条件1; then
    条件1为真的分支代码
elif 判断条件2; then
    条件2为真的分支代码
elif 判断条件3; then
    条件3为真的分支代码
...
else
    以上条件都为假的分支代码
fi

说明:

  • 多个条件时,逐个条件进行判断,第一次遇为“真”条件时,执行其分支,而后结束整个if语句 if 语句可嵌套。

范例:身体质量指数 (BMI)

#!/bin/bash
# ------------------------------------------
# Filename: hello.sh
# Version: 1.0
# Date: 202024/06/23
# Author: yang
# Email: 123456@qq.com
# Website: www.baidu.com
# Description: This is the first script
# Copyright: 2024 wang
# License: GPL
# ------------------------------------------
read -p "请输入身高(m为单位): " HIGH

if [[ ! "$HIGH" =~ ^[0-2]\.?[0-9]{,2}$ ]];then
    echo "输入错误的身高"
    exit 1
fi

read -p "请输入体重(kg为单位): " WEIGHT

if [[ ! "$WEIGHT" =~ ^[0-9]{1,3}$ ]];then echo "输入错误的体重"; exit 1; fi

BMI=`echo $WEIGHT/$HIGH^2|bc`

if [ $BMI -le 18 ] ;then
    echo "太瘦了,多吃点"
elif [ $BMI -lt 24 ] ;then
    echo "身材很棒!"
else
    echo "太胖了,注意节食,加强运动"
fi

3.2 条件判断case语句

格式:

case 变量引用 in
PAT1)
   分支1
   ;;
PAT2)
   分支2
   ;;
...
*)
   默认分支
   ;;
esac

case支持glob风格的通配符:

*: 任意长度任意字符
?: 任意单个字符
[]:指定范围内的任意单个字符
|:   或,如 a或b

范例:运维菜单实现

#!/bin/bash
# ------------------------------------------
# Filename: hello.sh
# Version: 1.0
# Date: 202024/06/23
# Author: yang
# Email: 123456@qq.com
# Website: www.baidu.com
# Description: This is the first script
# Copyright: 2024 wang
# License: GPL
# ------------------------------------------
echo -en "\E[$[RANDOM%7+31];1m"
cat <<EOF
请选择:
1)备份数据库
2)清理日志
3)软件升级
4)软件回滚
5)删库跑路
EOF
echo -en '\E[0m'
read -p "请输入上面数字1-5: " MENU
case $MENU in
1)
    echo "备份数据库"
    ;;
2)
    echo "清理日志"
    ;;
3)
    echo "软件升级"
    ;;
4)
    echo "软件回滚"
    ;;
5)
    echo "删库跑路"
  • 8
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值