Shell入门(一)变量和流程控制
2021/7/27 7:05:57
本文主要是介绍Shell入门(一)变量和流程控制,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
刚入职新公司,碰到一个棘手的线上莫名宕机问题。我需要查看应用日志,应用端口等信息,以前,只是知道tail -f service.log | grep '关键词'
这样的简单查询日志操作。另外,需要频繁打开应用目录,启动应用,然后切换到日志目录,查看日志,比较繁琐,后面我通过 Shell 的alias
功能,让操作得到一定程度的简化。但是,为了写出更好的执行脚本,于是有了这系列文章。
本系列文章分为两小节:
1,Shell 是什么?
2,Shell 基础
- 变量
- 流程控制
- 数组
- 函数
1,Shell 是什么?
简单来说,Shell 就是操作系统上运行的一个应用程序。
普通用户接触最多的操作系统是 Windows,而程序员使用更频繁的是 Linux 的服务端系统。
Windows 提供图形化界面,让我们可以通过移动光标,鼠标右键等一系列操作完成文件的编辑工作,降低普通用户的使用难度。
而程序员是以软件开发为职业,操作的是很少提供图形化界面的服务端系统,而 Shell 可以让用户更方便的操作 Linux 系统,
如文本或字符串检索,文件的查找或创建,大规模软件的自动部署,监控服务器性能,压缩文件等。
1.2,初识 Shell
- test.sh
#!/bin/bash echo "Hello World!"
1.3 shell 脚本 Debug 调试
- 基本写法:
sh [-nxv] 脚本
-n
: 读一遍脚本中的命令但不执行,用于检查脚本中的语法错误;-v
: 一边执行脚本,一边将执行过的脚本命令打印到标准输出;-x
:提供跟踪执行信息,将执行的每一条命令和结果依次打印出来;
2, Shell 基础
- 变量
- 流程控制
- 数组
- 函数
2.1 变量
- 自定义变量
- 系统环境变量
- 预先定义变量
2.1.1 自定义变量
- 定义变量:
变量名=变量值
- 引用变量:
$变量名
或${变量名}
- 查看变量:
echo $变量名
或者set
显示所有变量,包括自定义变量和环境变量
2.1.2 系统环境变量
- 定义环境变量:
export 变量名=变量值
- 引用环境变量:
$变量名
- 查看环境变量:
echo $变量名
或者env | grep 变量名
2.1.3 预先定义变量
$0
: 脚本文件名称$*
: 当前脚本传入的所有参数$@
: 当前脚本传入的所有参数$#
: 当前脚本传入参数的个数$$
: 执行当前脚本进程的 PID$!
: 上一个后台进程的 PID$?
: 上一个命令的返回值,0 表示成功执行
2.1.4 单引号和双引号的困惑
[root@roclinux ~]$ echo $PWD /root [root@roclinux ~]$ alias dirA="echo work directory is $PWD" [root@roclinux ~]$ alias dirB='echo work directory is $PWD' # 正确显示 [root@roclinux ~]$ dirA work directory is /root # 正确显示 [root@roclinux ~]$ dirB work directory is /root # 显示不正确, 怎么回事? [root@roclinux ~]$ cd / [root@roclinux /]$ dirA work directory is /root # 正确显示 [root@roclinux /]$ dirB work directory is / # 查看 alias 的真实内容 [roc@roclinux ~]$ alias dirA alias dirA="echo work directory is /root" [roc@roclinux ~]$ alias dirB alias dirB='echo work directory is $PWD'
- 示例来源:单引号和双引号的困惑
- 使用双引号的 dirA,通过 Shell 的变量转换后已经变成了字符串
echo work directory is /root
,当目录切换后,显示的还是原目录内容; - 使用单引号的 dirB,由于不受 Shell 的影响,仍然保留着原来的位置
echo work directory is $PWD
,当切换目录后再执行,变量$PWD
被 Shell 替换掉,因此内容被正确显示。 - 换句话说,双引号是弱引用,会解析变量,单引号是强引用,不会解析变量。
# 示例二: [xiaoa@linux ~]$ name=zhangsan [xiaoa@linux ~]$ echo 'My name is ${name}' My name is ${name} [xiaoa@linux ~]$ echo "My name is ${name}" My name is zhangsan
2.1.5 命令替换
\``\
命令等价于$()
# 示例一,创建文件 touch `date +%F`_file1.txt touch $(date +%F)_file2.txt # 示例二,查看可用磁盘容量 disk_free3="df -Ph | grep '/$' | awk '{print $4}'" # 错误 disk_free4=$(df -Ph | grep '/$' | awk '{print $4}') disk_free5=`df -Ph | grep '/$' | awk '{print $4}'`
2.1.6 变量数值运算
# 示例一: 整数运算 expr + - \* / % [xiaoa@linux ~]$ a=1 [xiaoa@linux ~]$ b=2 [xiaoa@linux ~]$ expr $a + $b 3 [xiaoa@linux ~]$ expr $a \* $b # 示例二:整数运算 let + - * / % [xiaoa@linux ~]$ let sum=2+3; [xiaoa@linux ~]$ echo $sum 5 # 示例三: 小数运算 bc + - * / % [xiaoa@linux ~]$ echo "1+2" |bc [xiaoa@linux ~]$ echo "scale=2;4/8" |bc
2.1.7 默认变量
${变量名-新的变量值}
:- 变量没有被赋值,会使用“新的变量值”替代;
- 变量有被赋值(包括空值):不会被替代
echo ${var1-test}
${变量名:-新的变量值}
:- 变量没有被赋值(包括空值),会使用“新的变量值”替代;
- 变量有被赋值:不会被替代
echo ${var1:-test}
2.2 流程控制
- 条件测试与逻辑运算表达式
- 流程控制语句
if
- 流程控制语句
case
- 循环语句
for
,while
2.2.1 条件测试 test
条件测试与逻辑运算表达式
- 基本语法
- 文件测试
- 数值比较
- 字符串比较
- 正则比较
2.2.1.1 基本语法
# 条件表达式 1,`test 条件表达式` 2,`[ 条件表达式 ]` 3,`[[ 条件表达式 ]]` # 逻辑运算表达式 命令 1 ; 命令 2 无论命令 1 是否执行成功都会执行命令 2 命令 1 && 命令 2 命令 1 必须执行成功,才会执行命令 2 命令 1 || 命令 2 命令 1 必须执行失败,才会执行命令 2
2.2.1.1 文件测试
man [
: 查看[
表达式用法;[ -e dir|file ]
: 目录或文件是否存在;[ -d dir ]
: 目录是否存在;[ -f file ]
: 文件是否存在;[ -r file ]
: 当前用户对该文件是否具有读权限;
# 判断目录是否存在,不存在,则创建该目录 test -d ~/Desktop/test || mkdir -p ~/Desktop/test
2.2.1.2 数值比较
[ 整数1 操作符 整数 2 ]
- 大于:
[ 1 -gt 10 ]
- 小于:
[ 1 -lt 10 ]
- 等于:
[ 1 -eq 10 ]
- 不等于:
[ 1 -ne 10 ]
- 小于等于:
[ 1 -le 10 ]
- 大于等于:
[ 1 -ge 10 ]
# 示例一:磁盘使用率大于 80, 打印输出 #!/bin/bash Disk_Free=$(df -h|grep "$"|awk '{print $5)'|awk -F '%' '{print $1}'}) if [ $Disk_Free -ge 80 ];then echo "Disk is Use: $Disk_Free%" > /tmp/disk_use.txt fi # 示例二:多整数比对 # -a: and [ 1 -lt 2 -a 5 -gt 10 ];echo $? # -o: or [ 1 -lt 2 -o 5 -gt 10 ];echo $? # && [ 1 -lt 2 && 5 -gt 10 ];echo $? # || [ 1 -lt 2 || 5 -gt 10 ];echo $?
2.2.1.3 字符串比较
[xiaoa@linux ~]$ name=zhangsan [xiaoa@linux ~]$ [ $name = "zhangsan" ]; echo $? 0 [xiaoa@linux ~]$ [ $name == "zhangsan" ]; echo $? 0 [xiaoa@linux ~]$ echo ${#name} # 计算字符长度 8 [xiaoa@linux ~]$ BBB="" [xiaoa@linux ~]$ echo ${#BBB} 0 [xiaoa@linux ~]$ [ -z "$BBB" ] 字符长度为 0 0 [xiaoa@linux ~]$ [ -n "$BBB" ] 字符长度不为 0 1 # 小结:变量为空或未定义,长度都为 0
2.2.1.4 正则比对
# 判断 name 是不是以 z 开头 [xiaoa@linux ~]$ [[ $name =~ ^z ]];echo $? 0 # 判断变量是不是数字 [xiaoa@linux ~]$ num=123 [xiaoa@linux ~]$ num2=123abc [xiaoa@linux ~]$ [[ $num =~ ^[0-9]+$ ]];echo $? 0 [xiaoa@linux ~]$ [[ $num2 =~ ^[0-9]+$ ]];echo $? 1
2.2.2 流程控制语句 if
# 单分支结构 if [ 分数大于 60 ];then echo "及格" fi # 双分支结构 if [ 分数大于 60 ];then echo "及格" else echo "不及格" fi # 多分支结构 if [ 分数大于 80 ];then echo "优秀" elif [ 分数大于 60 ];then echo "及格" else echo "不及格" fi
2.2.3 流程控制语句 case
case 变量 in 模式 1) 执行命令 1;; 模式 2) 执行命令 2;; 模式 3) 执行命令 3;; *) 执行默认命令 esac # 示例 1 #!/bin/bash case $1 in Linux) echo "linux ..." ;; Shell) echo "shell ..." ;; MySQL) echo "mysql ..." ;; *) # echo "USAGE $0 [Linux|Shell|MySQL]" echo "USAGE `basename $0` [Linux|Shell|MySQL]" esac # 示例 2 #!/bin/bash read -p "Are you sure?[y/n]:" action case "$action" in y|Y|yes|YES) echo "user is deleted!" ;; *) echo "error" esac # 示例 3: 系统工具 #!/bin/bash cat <<-EOF =================== h 显示命令帮助 f 显示磁盘分区 d 显示磁盘挂载 m 查看内存使用 u 查看系统负载 q 退出程序 =================== EOF while true do read -p "请输入你想查看的系统状态对应码[d/m/u/q] " sys case $sys in h) help|less ;; f) clear lsblk ;; d) clear df -h ;; m) clear free -m ;; u) clear uptime ;; q) break ;; *) echo "error" exit 1; esac done
2.2.4 循环语句
2.2.4.1 for
循环
# 基本语法 for 变量名 [ in 取值列表 ] do 循环体 done # 示例 1: 计算 1 到 100 的和 #!/bin/bash sum=0 for i in {1..100} do let sum=sum+$i done echo $sum # 示例 2:计算 1 到 100 之间所有奇数的和 #!/bin/bash sum=0 for i in `seq 1 2 100` do let sum=sum+$i done echo $sum
2.2.4.2 while
循环
# 基本语法 while 条件测试 do 循环体 done # 示例 1:计算 1~100 的和 #!/bin/bash i=1 sum=0 while [ $i -le 100 ] do let sum=sum+$i # 注意:此处没有空格 let i++ done echo $sum # 示例 2: 猜数字游戏 #!/bin/bash sum=$((RANDOM%51)) sleep 1 echo "请输入1-50之间的数,开始猜吧!" count=0 function type_num(){ read -p "请输入一个数吧:" n expr $n + 1 &>/dev/null if [ $? -ne 0 ]; then echo "请输入一个数字" type_num fi } function guess(){ (( count++ )) if [ $n -eq $sum ]; then echo "你猜中了,你的次数是:"${count} if [ $count -lt 3 ]; then echo "你太厉害了" elif [ $count -ge 3 -a $count -lt 6 ]; then echo "还是不错的,加油" else echo "你有点水啊" fi exit 0 elif [ $n -gt $sum ]; then echo "猜大了" type_num else echo "猜小了" type_num fi } function main(){ type_num while true do guess done } main
**参考资料:**
- Shell 基础
- Shell 自动化编程实战
这篇关于Shell入门(一)变量和流程控制的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-13怎么通过 JavaScript 或其他编程语言来实现监听屏幕高度变化功能?-icode9专业技术文章分享
- 2024-11-12聊聊我们那些年用过的表达式引擎组件
- 2024-11-12让项目数据更有说服力:五款必备数据可视化管理工具推荐
- 2024-11-12人到一定年纪,要学会远离多巴胺
- 2024-11-12解读:精益生产管理的目的是什么?如何操作?
- 2024-11-12Sku预研作业
- 2024-11-12文心一言API密钥:分步申请指南
- 2024-11-12初学者指南:轻松掌握后台交互
- 2024-11-12从零开始学习:封装基础知识详解
- 2024-11-12JSON对象入门教程:轻松掌握基础用法