Linu进阶-Shell编程入门上 hf
一, Shell编程入门
- 为什么大数据需要学习shell编程
- 需要看懂运维人员编写的Shell程序;
- 管理集群(编写集群时间同步的crontab脚本, 定时维护数据库等等);
- 什么是shell?
- shell是一个命令行解释器,它接收应用程序/用户的命令, 然后调用操作系统内核, 它是用户使用操作系统的桥梁;
- shell编程就是对一堆Linux命令的逻辑化处理;
- Shell环境
二, 第一个shell脚本
要点:
-
脚本以 #!/bin/bash 开头
-
脚本被赋予执行权限
-
也可以不赋予执行权限, 而使用
sh xx.sh
来执行脚本(不推荐)
-
Shell脚本文件以.sh为后缀, 但是也可以.txt等后缀
-
脚本可相对路径执行, 也可绝对路径执行
脚本编写如下:
#!/bin/bash
echo "Hello, are u sb?"
图示如下:
注意:
三, shell变量
3.1 变量的一些约束和命名规则
变量名和等号之间不能有空格
; 同时变量的命名有以下规则:
- 命名只能使用英文字母, 数字和下划线, 不能以数字开头;
- 变量中间不存在空格, 可以使用下划线;
- 不能使用标点符号;
- 不能使用bash中的关键字
- 变量名一般为全大写
举个栗子:
[注意]
-
在bash中,变量默认类型都是字符串类型,无法直接进行数值运算。
-
变量的值如果有空格,需要使用双引号或单引号括起来。
3.2 shell变量的种类
按照变量的作用域, shell变量被分为了 局部变量, 环境变量, shell变量
运行shell时,会同时存在这三种变量:
-
局部变量 局部变量在脚本或命令中定义,仅在当前shell实例中有效,其他shell启动的程序不能访问局部变量。
-
环境变量 所有的程序,包括shell启动的程序,都能访问环境变量,有些程序需要环境变量来保证其正常运行。必要的时候shell脚本也可以定义环境变量。
- 自定义环境变量
- 自定义环境变量
-
shell变量 shell变量是由shell程序设置的特殊变量。shell变量中有一部分是环境变量,有一部分是局部变量,这些变量保证了shell的正常运行
tips: 在shell里如何使用多行注释?
3.3 对变量的操作
3.3.1 使用变量(${变量名})
使用一个定义过了的变量, 我们需要在变量前面加上美元符号
;
举个栗子:
变量名外面的
花括号
是可选的, 其主要作用是为了帮助解释器识别变量的边界;
3.3.2 使变量只读(readonly 变量名)
使用 readonly命令可以将变量定义为只读变量, 只读变量的值不能被改变;
- 举个栗子:
3.3.3 删除变量(unset 变量名)
使用unset命令可以删除变量;
注意: 只读变量无法被删除
- 举个栗子
只读变量无法被删除:
3.3.4 将linux命令的结果赋给变量(重要)
两种方法
- 使用
反引号
, 例如: A=`ls `$(命令)
, 例如: A=$(ls)
图示如下:
3.4 Shell位置参数变量
[定义]
在Linux的命令行中, 当一条命令或脚本执行时, 后面可以跟多个参数
, 我们使用位置参数变量来表示这些参数;
其中, $0表示命令行本身, $1代表执行脚本时添加的第一个参数, $2代表添加的第二个参数, 以此类推.
当参数个数超过10个时, 就要用大括号把这个数字括起来, 例如, ${10}道代表第10个参数, ${14}代表第14个参数.
图示如下:
在shell中可以识别的位置参数变量及含义如下表所示:
位置参数变量 | 作用 |
---|---|
$n | n为数字, $0代表命令本身, $1-$9代表1-9个参数, 10以上的参数需要用大括号包含, 如 ${10} |
$* | 代表命令行中所有的参数, 把所有的参数看作是一个整体 |
$@ | 代表命令行中所有的参数, 不过 $@把每个参数区别对待 |
$# | 代表命令行中所有参数的个数 |
图示如下:
3.5 shell预定义变量
[定义]
预定义变量是在Shell一开始时就定义的变量,这一点和默认环境变量有些类似. 不同的是, 预变量不能重新定义, 用户只能根据Shell的定义来使用这些变量;
严格来说, 位置参数变量也是预定义变量的一种, 只是位置参数变量的作用比较统一, 所以我们把位置参数变量单独划分为一类变量;
预定义变量
|预定义变量|作用|
|$?| 表示最后一次执行的命令的返回状态
。如果这个变量的值为0,证明上一个命令正确执行
;如果这个变量的值为非0(具体是哪个数,由命令自己来决定),则证明上一个命令执行不正确了
。|
|$$|当前进程的进程号(PID)|
|$!|后台运行的最后一个进程的进程号(PID)|
图示如下:
$? 的使用
$$ 和 $!的使用
============================ 7.14
四, 运算符
4.1 算数运算符
[基本语法]
- 不使用expr的运算写法, " $((运算式))" 或 " $[运算式] "
- expr $m + $n 注意
expr, 运算式, 运算符号之间的空格一个都不能少
- expr 加+, 减-, 乘*, 除/, 取余%
- 我们可以对比复习一下命令结果的传递, 使用反引号 `命令`, 或者是
$(命令)
- 再对比复习一下, 使用某个变量, 命令是 变 量 名 < / k b d > , 如 果 是 帮 助 解 释 器 识 别 边 界 还 需 写 成 < k b d > 变量名</kbd>, 如果是帮助解释器识别边界还需写成<kbd> 变量名</kbd>,如果是帮助解释器识别边界还需写成<kbd>{变量名}
算术运算符
[案例实操]
4.2 关系运算符
[常用运算符和用法]
关系运算符只支持数字, 不支持字符串, 除非字符串的值是数字;
下表列举了常用的关系运算符, 假定变量a为10, b为20;
运算符 | 说明 | 举例 |
---|---|---|
-eq (equal等于) | 检测两个数是否相等, 相等返回true | [ $a -eq $b ] 返回false |
-ne (not equal不等于) | 检测两个数是否不相等, 不相等返回true | [ $a -ne $b ]返回true |
-gt (greater than大于) | 检测左边的数是否大于右边的,是返回true | [ $a -gt $b ] 返回false |
-lt (less than小于) | 检测左边的数是否小于右边的, 如果是,则返回true | [ $a -lt $b ]返回true |
-ge (greater equal大于等于) | 检测左边的数是否大于等于右边的, 是则返回true | [ $a -ge $b ]返回true |
-le (less equal小于等于) | 检测左边的数是否小于等于右边的,是则返回true | [ $a -ls $b ] 返回false |
[案例实操]
五, 条件判断
[基本语法]
# 注意: condition前后一定要有空格!!!!
[ condition ]
[常用判断条件]
- 两个整数之间比较
- 字符串比较 =
- 数字比较:
-
按照文件权限进行判断
-
按照文件类型判断
[案例实操]
-
判断test文件是否存在
-
判断字符是否相同
-
判断文件是否存在,是否是一个目录
- 多条件判断(&& 表示前一条命令命令执行成功时,才执行后一条命令, || 表示上一条命令执行失败后, 才执行下一条命令)
六, 流程控制
6.1 if判断
[基本语法]
- if
if [ 条件判断式 ]
then
command1
command2
...
fi
- if else
if [ 条件判断式 ]
then
command1
command2
...
else
command
fi
- if else-if else
if [ 条件判断式1 ]
then
command1
elif [ 条件判断式2 ]
then
command2
else
comandN
fi
注意:
- 条件判断式不要忘了两边的空格, if后面也得有空格
- 对于shell程序, 规定流程控制的分支不能为空, 例如: 如果 else 分支没有语句执行,就不要写这个 else。
[案例实操]
- 编写一个shell程序, 如果输入的参数,大于等于60, 则输出"及格了", 如果小于60, 则输出"不及格"
- 判断a,b两个变量的大小关系
6.2 case…esac语句
case…esac为多选择语句, 与其他语言中的switch…case语句类似, 是一种多分支选择结构, 每个case分支用模式)右圆括号开始, 用两个分号;;表示break, 即执行结束, 跳出整个 case…esac语句, esac(就是case反过来)作为整个case语句的结束标记;
[基本语法]
case 值 in
模式1)
command1
command2
....
;;
模式2)
command1
command2
...
;;
esac
- case 工作方式如上所示, 取值后面必须为单词in, 每一模式必须以右括号结束. case 值 in
- 取值将检测匹配的每一个模式. 一旦模式匹配, 则执行完匹配模式相应命令后不再继续其他模式. 如果无一匹配模式, 使用星号 * 捕获该值, 再执行后面的命令;
[案例实操]
- 下面的脚本提示输入 1 到 4,与每一种模式进行匹配:
- 下面的脚本匹配字符串:
![]](https://img-blog.csdnimg.cn/20210522111748383.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L25tc0xMQ1NETg==,size_16,color_FFFFFF,t_70#pic_center)
6.3 for循环
[基本语法 1.]
for ((初始值;循环控制条件;变量变化))
do
循环程序段
done
[基本语法 2.]
for 变量 in 值1 值2 值3 ...
do
对变量循环的程序段
done
[案例实操]
- 从1加到10
-
输入1,2,3,4,5
-
输入字符串
$* 和 $@的辨析
先看一个借助for循环实现的栗子:
-
使用 #*作为循环的对象
-
使用 #@作为循环的对象
总结如下:
- #*和#@都表示传递给函数或脚本的所有参数,不被双引号“”包含时,都以$1 $2 …$n的形式输出所有参数。
- 当它们被双引号“”包含时,“$*”会将所有的参数作为一个整体,以“$1 $2 …$n”的形式输出所有参数;“$@”会将各个参数分开,以“$1” “$2”…”$n”的形式输出所有参数。
6.4 while循环
[基本语法]
while [ 条件判断式 ]
do
循环程序段
done
[案例实操]
-
从1加到100
七, read读取控制台输入
[基本语法]
read (选项) (参数)
选项:
-p: 指定读取值时的提示符;
-t: 指定读取值时等待的时间(秒);
参数:
变量: 指定读取值的变量名;
[案例实操]
八, 函数
8.1 系统函数
shell 编程和其它编程语言一样,有系统函数,也可以自定义函数。系统函数中,我们这里就先介绍下面两个
8.1.1 basename
[基本用法和用途]
功能: 常用于获取文件名(即文件路径最后一个正斜杠’/'后面的内容)
基本语法:
basename [pathname] [suffix]
选项:
suffix 为后缀,如果 suffix 被指定了,basename 会将 pathname 或 string 中的 suffix 去掉。
[案例实操]
![]](https://img-blog.csdnimg.cn/20210522112222510.png#pic_center)
8.1.2 dirname
[基本用法和用途]
功能: 常用于返回路径部分(即文件路径中除了最后一个正斜杠’/'前面的部分)
基本语法:
dirname 文件绝对路径
[案例实操]
8.2 自定义函数
[基本语法]
function 函数名(){
程序段
return 返回值
}
- function 是shell中的关键字, 专门用来定义函数;
- return 返回值 表示函数的返回值, 其中 return 是shell关键字, 专门在函数中返回一个值, 这个字段可写可不写;
注意: shell中函数的两种简化写法如下
简化写法1:
# 省略 function 关键字
函数名(){
程序段
[return value]
}
简化写法2:
#如果写了function关键字, 也可以省略函数名后的小括号
function name{
程序段
[return value]
}
对 返回值的说明
函数返回值,只能通过$?系统变量获得,可以显示加:return返回,如果不加,将以最后一条命令运行结果,作为返回值。return后跟数值n(0-255)
[函数的调用]
调用shell函数时可以给它传递参数, 也可以不传递. 如果不传递参数, 直接给出函数名字即可;
name
如果传递参数, 那么多个参数之间以空格分隔:
name param1 param2 param3
和其它编程语言不同的是,Shell 函数在定义时不能指明参数,但是在调用时却可以传递参数,并且给它传递什么参数它就接收什么参数。
Shell 也不限制定义和调用的顺序,你可以将定义放在调用的前面,也可以反过来,将定义在调用的后面。
[案例实操]
-
一个简单的打印函数, 并且函数在调用时传入了参数
-
定义一个函数,计算所有参数的和
$@表示函数的所有参数,$?表示函数的退出状态(返回值)