本文主要是介绍linux Shell脚本指南(条件判断、expr执行运算、流程控制、使用函数处理文件、cut、awk、sort、邮件发送) 删除文件脚本 读可用内存发送邮件脚本,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
文章目录
- 前言
- 1. 脚本格式和执行方式
- 1.1 脚本格式
- 1.2 第一个Shell脚本
- 1.3 常用执行方式
- (1)采用bash/sh加脚本的相对路径或绝对路径(不用赋予脚本执行权限即可)
- (2)采用输入脚本的绝对路径或相对路径执行脚本(必须具有可执行权限)
- 2. 变量
- 2.1 系统预定义变量
- 2.2 自定义变量
- 2.3 特殊变量
- 3. 字符串、运算符、注释
- 3.1 字符串
- (1) 单引号
- (2) 双引号
- 3.2 运算符
- 3.3 注释
- 4. 条件判断
- 4.1 语法
- 4.2 常用判断条件
- 5. 流程控制
- 5.1 if判断
- 5.2 case语句
- 5.3 for循环
- 5.4 while循环
- 6. read读取控制台输入
- 7. 函数
- 7.1 系统函数
- (1)basename 获取文件名
- (2)dirname 获取目录
- (3)提取文件后缀
- 7.2 自定义函数
- 8. Shell工具
- 8.1 cut
- 8.2 awk
- 8.3 sort
- 9. 正则表达式
- 9.1 概念
- 9.2 常规匹配
- 9.3 常用特殊字符
- 10. 邮件发送(以163邮箱为例)
- 10.1 163邮箱启用smtp服务
- 10.2 linux服务器发送邮件
- 工作中常用脚本(使用crontab定时调度)
- 1. 删除文件脚本
- 2. 读取服务器可用内存数量,发送邮件
前言
Shell 是一个用 C 语言编写的程序,是用户使用 Linux 的桥梁,既是一种命令语言,又是一种程序设计语言。Shell 是Linux系统的用户界面,提供用户与内核的一种交互方式
,接收用户输入的命令,并把它送入内核去执行
Linux提供的Shell解析器:
/bin/sh
/bin/bash
/sbin/nologin
/usr/bin/sh
/usr/bin/bash
/usr/sbin/nologin
/bin/tcsh
/bin/csh
Centos默认的解析器是bash:
1. 脚本格式和执行方式
1.1 脚本格式
脚本以#!/bin/bash
开头(指定解析器)
1.2 第一个Shell脚本
编写脚本,文件后缀为.sh,输出当前时间:
#!/bin/bash
echo "当前时间:"
date "+%Y-%m-%d %H:%M:%S"
1.3 常用执行方式
(1)采用bash/sh加脚本的相对路径或绝对路径(不用赋予脚本执行权限即可)
sh var.sh
或
bash var.sh
(2)采用输入脚本的绝对路径或相对路径执行脚本(必须具有可执行权限)
若脚本没有指定路径,linux 系统会遍历$PATH
即环境变量寻找脚本
(a)赋予脚本执行权限
chmod u+x var.sh
(b)执行脚本
相对路径执行:
./var.sh
注:
方法一,本质是使用bash解析器执行脚本,所以脚本不需要执行权限
方法二,本质是脚本需要自己执行,所以需要执行权限
2. 变量
2.1 系统预定义变量
常用系统变量$HOME、$PWD、$SHELL、$USER
注:
显示当前Shell中所有变量:
set
如:
(a)查看环境变量:
set |grep path
(b)查看自定义变量
set |grep tomcat
2.2 自定义变量
(1)语法
定义变量:变量=值
撤销变量:unset 变量
声明静态变量:readonly 变量
(不能unset)
如:
(a)给变量A重新赋值
#!/bin/bash
A=5
A=8
echo $A
(b)撤销变量A
#!/bin/bash
A=5
unset A
echo $A
(c)声明静态的变量B=2,unset
#!/bin/bash
readonly B=5
echo $B
unset B=6
echo $B
B=9
(d)用语句给变量赋值
A=$(ls /etc/profile.d)
B=`ls /etc/profile.d/`
#!/bin/bash
#for file in $(ls /etc/profile.d)
for file in `ls /etc/profile.d/`
do
echo $file
done
(2)变量定义规则
变量名称可以由字母、数字和下划线组成,但是不能以数字开头
,环境变量名建议大写
等号两侧不能有空格
在bash中,变量默认类型都是字符串类型,无法直接进行数值运算
变量的值如果有空格,需要使用双引号或单引号括起来
如:
(a)变量是字符串类型,无法直接进行数值运算
#!/bin/bash
A=5
B=6
C=$A+$B
echo $C
D=`expr $A + $B`
echo $D
(b)变量的值如果有空格,需要使用双引号或单引号括起来
#!/bin/bash
A=i love you
B="i love you"
echo $A
echo $B
(3)使用变量
${变量名}
变量名外面的花括号可选
,加不加都行,加花括号是为了帮助解释器识别变量的边界
如:
(a)定义变量A,按照变量A拼接s cz输出
#!/bin/bash
A=5
echo ${A}s cz
(b)可把变量提升为全局环境变量,可供其他Shell程序使用
export 变量名
2.3 特殊变量
2.3.1 $n
n为数字,$0代表该脚本名称,$1-$9代表第一到第九个参数,十以上的参数,十以上的参数需要用大括号包含,如${10}
2.3.2 $#
获取所有输入参数个数,常用于循环
2.3.3 $*、$@
代表命令行中所有的参数,$*把所有的参数看成一个整体
,而$@把每个参数区分对待
注:
$*、$@
都表示传递给函数或脚本的所有参数,不被双引号
包含时,都以$1 $2 …$n
的形式输出所有参数
当被双引号包含时,$*
会将所有的参数作为一个整体,以"$1 $2 …$n"
的形式输出所有参数;$@
会将各个参数分开,以"$1" "$2"…"$n"
的形式输出所有参数
2.3.4 $?
最后执行的命令的返回状态。如果返回的值为0,证明上一个命令正确执行;如果值为非0(具体数字取决于命令),则证明上一个命令执行不正确
2.3.5 数组
用括号( )来表示数组,不支持多维数组,数组元素之间用空格来分隔;获取数组元素的值,使用${数组名[下标]}; 使用@或*可以获取数组中的所有元素${数组名[*]} ${数组名[@]}
,下标由 0 开始编号
(1)定义数组
数组名=(值1 值2 ... 值n)
单独定义数组的元素:
数组名[下标]=值
如:
定义一个数组,修改下标0值为10:
arr=(5 10 20 30)
echo ${arr[*]}
arr[0]=10
echo ${arr[*]}
(2)读取数组
${数组名[下标]}
如:
遍历一个数组:
(3)获取数组的长度
length=${#数组名[@]}
或
length=${#数组名[*]}
如:
获取数组arr的长度:
arr=(10 2 5 78)
echo ${#arr[*]}
echo ${#arr[@]}
3. 字符串、运算符、注释
3.1 字符串
(1) 单引号
规则:
单引号里的任何字符都会原样输出,单引号字符串中的变量是无效的
;
单引号字串中不能出现单独一个的单引号
(对单引号使用转义符后也不行),但可成对出现,作为字符串拼接使用
如:
单引号内变量无效:
一个单引号不能单独出现:
(2) 双引号
规则:
双引号里可以有变量
双引号里可以出现转义字符
获取字符串长度
echo ${#字符串变量}
提取子字符串(第一个字符的索引值为 0)
echo ${字符串变量:1:4}
查找字符
出现的位置 (子字符串为fd则查找字符 f 或 d的位置(哪个字母先出现就计算哪个))
echo `expr index $字符串变量 子字符串`
如:
3.2 运算符
(1)原生bash不支持简单的数学运算,但是可以通过其他命令来实现。expr 是一款表达式计算工具,使用它能完成表达式的求值操作
如:
计算 2 + 2:
#!/bin/bash
var=`expr 2 + 2`
echo ${var}
注: expr 表达式和运算符之间要有空格
,如 2+2 是不对的,必须写成 2 + 2;
计算10*2:
var=`expr 10 \* 2`
echo $var
注:乘号*前边必须加反斜杠(\)才能实现乘法运算
(2)算术运算符
$((运算式))
或
$[运算式]
如:
计算(2+3)乘以50
A=$[(2+3)*50]echo $A
或
unset A
A=$(((2+3)*50))
echo $A
3.3 注释
以 # 开头的行就是注释,会被解释器忽略;多行注释:<<EOF 注释内容 EOF
#!/bin/bash
#注释
:<<EOF
注释
注释
EOF
4. 条件判断
4.1 语法
test condition
或
[ condition ]
(注意condition前后要有空格)
注:条件非空即为true
,[ rng ]返回true,[] 返回false
4.2 常用判断条件
(1)两个整数之间比较
== 等于
-lt 小于(less than)
-le 小于等于(less equal)
-eq 等于(equal)
-gt 大于(greater than)
-ge 大于等于(greater equal)
-ne 不等于(Not equal)
(2)按照文件权限进行判断
-r 有读的权限(read)
-w 有写的权限(write)
-x 有执行的权限(execute)
(3)按照文件类型进行判断
-f 存在一个文件(file)
-e 文件存在(existence)
-d 存在一个目录(directory)
(4)字符串比较
假定变量 a 为 “A”,变量 b 为 “a”:
运算符 | 说明 |
---|---|
= | 检测两个字符串是否相等,相等返回 true |
!= | 检测两个字符串是否不相等,不相等返回 true |
如:
(1)-1和-5大小比较
[ -5 -ge -1 ]
echo $?test -1 -ge -5
echo $?
(2)var.sh是否具有写权限
test -w var.sh
echo $?
(3)/root/a.txt 目录中的文件是否存在
[ -e /root/a.txt ]
echo $?
(4)多条件判断(&& 表示前一条命令执行成功时,才执行后一条命令,|| 表示上一条命令执行失败后,才执行下一条命令)
[ 5 -eq 5 ] && echo $USER || echo no
(5)比较字符串A和a
—
5. 流程控制
5.1 if判断
if [ 条件判断式 ]
then 程序
fi
或者
if [ 条件判断式 ]
then 程序
elif [ 条件判断式 ]
then程序
else程序
fi
注:
[ 条件判断式 ] 中括号和条件判断式之前必须有空格
; if后有空格
如:
输入参数为1,则输出中国
#!/bin/bash
echo $0
if [ $1 -eq 1 ]then
echo "中国"
fi
输入参数为1,则输出中国;输入2为美国;其余为英国
#!/bin/bash
echo $0
if [ $1 -eq 1 ]then
echo "中国"
elif [ $1 -eq 2 ]
then
echo "美国"
else
echo "英国"
fi
5.2 case语句
case ${变量名} in "值1") 程序1 ;; "值2") 程序2 ;; *) 默认则执行此程序 ;;
esac
注:
case行尾必须为单词 in
,每一个模式匹配必须以右括号)
结束
双分号;;
表示命令序列结束,相当于java中的break
最后的*)
表示默认模式,相当于java中的default
如:
输入参数为1,则输出中国;输入2为美国;其余为英国
#!/bin/bash
echo $0
case $1 in"1")
echo 中国
;;"2")
echo 美国
;;*)
echo 英国
;;esac
5.3 for循环
语法1:
for (( 初始值;循环控制条件;变量变化 )) do 程序 done
语法2:
for 变量 in 值1 值2 值ndo 程序 done
如:
(1)从1加到100
#!/bin/bash
for((i=1;i<=100;i++))
do
s=$[$s+$i]
done
echo $s
(2)打印所有输入参数
#!/bin/bash
echo $0
for i in "$@"
do
echo $i
done
5.4 while循环
while [ 条件判断式 ] do 程序done
如:
从1加到100
#!/bin/bash
i=1
s=0
while [ $i -le 100 ]
do
s=$[$s+$i]
i=$[$i+1]
done
echo $s
6. read读取控制台输入
read (选项) (参数)
选项:
-p:指定读取值时的提示符;
-t:指定读取值时等待的时间(秒)
参数
变量:指定读取值赋予的变量
如:
提示7秒内,读取控制台输入的名称
#!/bin/bash
read -p "7秒内输入密码:" -t 7 passwd
echo $passwd
7. 函数
7.1 系统函数
(1)basename 获取文件名
basename命令会删掉所有的前缀包括最后一个/
字符,然后将字符串显示出来;suffix为后缀,如果被指定,basename会将path的后缀去掉
basename [path] [suffix]
如:
截取输入参数 /root/var.sh 的文件名称
#!/bin/bash
basename $1 .sh
(2)dirname 获取目录
从给定的包含绝对路径的文件名中去除文件名(非目录的部分),然后返回剩下的路径(目录的部分)
dirname 文件绝对路径
如:
截取输入参数 /root/var.sh 的文件目录
#!/bin/bash
dirname $1
(3)提取文件后缀
m=`basename ./MySQL5.7/libaio-0.3.109-13.el7.x86_64.rpm`
echo ${m##*.}
7.2 自定义函数
定义函数
function 方法名()
{逻辑脚本[return 整数值]
}
调用函数
方法名 [参数列表]
必须在调用函数之前,先声明函数,shell脚本是逐行运行,不会像其它语言一样先编译
函数返回值,只能通过$?
系统变量获得,可以显示加:return
返回,如果不加,将以最后一条命令运行结果,作为返回值。return后跟数值n(0-255)
如:
计算两个输入参数的和
#!/bin/bash
function sum()
{
total=$(($1+$2))
echo $total
}read -p "10s内输入参数1:" -t 10 num1
read -p "10s内输入参数2:" -t 10 num2
sum $num1 $num2
或
#!/bin/bash
function sum()
{
return $[$1+$2]
}read -p "10s内输入参数1:" -t 10 num1
read -p "10s内输入参数2:" -t 10 num2
sum $num1 $num2
8. Shell工具
8.1 cut
cut是在文件中负责剪切数据。cut 命令从文件的每一行剪切字节、字符和字段并将这些字节、字符和字段输出
语法: (默认分隔符是制表符,分隔符必须是单个字符
)
cut [选项参数] filename
选项参数 | 功能 |
---|---|
-f | 列号,提取第几列 |
-d | 分隔符,按照指定分隔符分割列 |
-c | 指定具体的字符 |
如:
(1)数据准备 a.txt
第一个参数为 1 !
第二个参数为 2 !
第十个参数为 10 !
第十个参数为 34 !
第十一个参数为 73 !
参数总数有 11 个!
作为一个字符串输出所有参数 1 2 3 4 5 6 7 8 9 34 73 !
(2)切割第一列
cut -f 1 -d " " a.txt
(3)切割第二、三列
cut -f 2,3 -d " " a.txt
(4)切割第二列以后所有
cut -f 2- -d " " a.txt
(5)在文件中切割出"参数总数"所在列(grep搜索pattern匹配的行
)
cat a.txt |grep "参数总数"
cat a.txt | grep "参数总数" | cut -d " " -f 1
(6)选取系统PATH变量值,第2个":"开始后的所有路径:
echo $PATH
echo $PATH|cut -d ":" -f 2-
(7)切割ifconfig 后打印的IP地址
ifconfig ens33|grep netmask|cut -d "t" -f 2|cut -d " " -f 2
8.2 awk
一个强大的文本分析工具,把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行分析处理
awk [选项参数] 'pattern1{action1} pattern2{action2} pattern3{action3}' 文件名
pattern:表示AWK在数据中查找的内容,就是匹配模式
action:在找到匹配内容时所执行的一系列命令
选项参数 | 功能 |
---|---|
-F | 指定输入文件折分隔符 |
-v | 给一个用户定义变量 赋值 |
awk的内置变量
变量 | 说明 |
---|---|
FILENAME | 文件名 |
NR | 已读的记录数(行数) |
NF | 浏览记录的域的个数(切割后,列的个数) |
如:
(1)数据准备
cp /etc/passwd ./
(2)搜索passwd文件以root关键字开头的所有行,并以:分隔输出该行的第7列
awk -F ":" '/^root/{print $7}' passwd
(3)搜索passwd文件以root关键字开头的所有行,并以:分隔输出该行的第1列和第7列,结果以,号分割
awk -F ":" '/^root/{print $1","$7}' passwd
(4)以:分隔输出/etc/passwd以root关键字开头的行的第一列和第七列,结果以逗号分割,且在所有行前面添加列名user,shell在最后一行添加 no
awk -F ":" 'BEGIN{print "user"} /^root/{print $1","$7} END{print "no"}' passwd
注:BEGIN 在所有数据读取行之前执行;END 在所有数据执行之后执行
(5)将passwd文件中的用户id增加数值1并输出
awk -F ":" -v a=1 '{print $3+a}' passwd
(6)统计以:分隔的passwd文件名,每行的行号,每行的列数
awk -F ":" '{print "文件名:" FILENAME " 行号:" NR "当前行列数:" NF }' passwd
(7)切割IP
ifconfig ens33 |awk -F "t" '/netmask/{print $2}'|awk -F " " '{print $1}'
8.3 sort
sort命令将文件进行排序,并将排序结果标准输出。
sort (选项) (参数)
选项 | 说明 |
---|---|
-n | 依照数值的大小排序 |
-r | 以相反的顺序来排序 |
-t | 设置排序时所用的分隔字符 |
-k | 指定需要排序的列 |
参数:指定待排序的文件列表
如:
以:分隔的passwd倒序排序
sort -n -r -t : -k 3 passwd
9. 正则表达式
9.1 概念
正则表达式使用单个字符串来描述、匹配一系列符合某个规则的字符串。在很多文本编辑器里,正则表达式通常被用来检索、替换那些符合某个模式的文本。在Linux中 grep,sed,awk等命令都支持通过正则表达式进行模式匹配
9.2 常规匹配
一串不包含特殊字符的正则表达式匹配它自己
cat /etc/passwd | grep rng
9.3 常用特殊字符
(1)^
匹配一行的开头
如:
cat /etc/passwd | grep ^root
匹配出所有以root开头的行
(2)$
匹配一行的结束
如:
cat /etc/passwd | grep t$
会匹配出所有以t结尾的行
注:^$
匹配空行
(3).
匹配一个任意的字符
如:
cat /etc/passwd | grep r..t
(4)*
不单独使用,它和左边第一个字符连用,表示匹配上一个字符0次或多次
如:
cat /etc/passwd | grep ro*t
(5)[ ]
表示匹配某个范围内的一个字符
[6,8]------匹配6或者8
[a-z]------匹配一个a-z之间的字符
[a-z]*-----匹配任意字母字符串
[a-c, e-f]-匹配a-c或者e-f之间的任意字符
如:
cat /etc/passwd | grep r[a,b,c]*t
(6)\
表示转义,并不会单独使用,转义字符和特殊字符连用,来表示特殊字符本身
10. 邮件发送(以163邮箱为例)
10.1 163邮箱启用smtp服务
开启SMTP服务
获取授权码和服务器地址
10.2 linux服务器发送邮件
(1)查看mail (无此命令则yum安装)
mail
(2)配置发送邮箱
set from=邮箱@163.com
set smtp=smtp.163.com
set smtp-auth-user=邮箱@163.com
set smtp-auth-password=授权码
set smtp-auth=login
(3)发送邮件
如:
接收邮件成功:
工作中常用脚本(使用crontab定时调度)
1. 删除文件脚本
#!/bin/bash
#输入参数1为文件的目录 输入参数2为目录大小达到多少进行删除
A=`du -sm ./|cut -f 1`
echo "$1大小为$A"
test $A -ge $2
echo $?
if [ $A -ge $2 ]
thenfor i in `find $1 -type f`
do
m=`basename $i`
echo "-------"
echo $m
echo ${m##*.}
rm -rf $i
donefi
2. 读取服务器可用内存数量,发送邮件
#!/bin/bash
FreeMem=`free -m |awk 'NR==2 {print $NF}'`if [ $FreeMem -lt $1 ]
then
echo "内存(M):$FreeMem " | tee /tmp/mes.txt
mail -s "`date '+%Y-%m-%d %H:%M:%S'` $FreeMem" 地址@163.com < /tmp/mes.txtfi
这篇关于linux Shell脚本指南(条件判断、expr执行运算、流程控制、使用函数处理文件、cut、awk、sort、邮件发送) 删除文件脚本 读可用内存发送邮件脚本的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!