Shell脚本
入门
格式:
以**#!/bin/bash** 开头(指定解析器)
创建
创建shell脚本,输出 helloworld
#!/bin/bash
echo "hello world"
执行
-
使用
bash
或者sh
执行bash hello.sh sh hello.sh
-
直接输入.sh全路径名称或者相对路径名称执行
/home/admin/hello.sh ./hello.sh
-
使用
source
或.
命令执行source hello.sh
1和2两种方式相当于子shell
,嵌套执行shell脚本,第3种方式相当于将内容提取到当前bash执行,嵌套shell中父子bash环境变量可能不一致
变量
变量分类,系统和用户,全局和局部
用户自定义变量
#查看当前所有环境变量
env
#查看当前Shell所有变量
set
#自定义变量
my_var="hello world"
echo my_var
#变量提升
export my_var
#计算变量
a=$[2+3]
a=$((2+3))
#只读变量
readonly b=10
#撤销变量
unset a
特殊变量
- $n: n为数字,$0代表脚本名称,$1- 9 代表第 1 − 9 个参数 , 十以上的参数 9代表第1-9个参数,十以上的参数 9代表第1−9个参数,十以上的参数{10}
- $#: 参数个数
- $*: 获取所有参数,将所有参数看做整体
- $@: 获取所有参数,将每个参数区分对待
- $?: 最后一次执行脚本的返回状态
parameter.sh
#!/bin/bash
echo '==========$n============'
echo bash name: $0
echo 1st : $1
echo 2nd: $2
echo '==========$#=========='
echo param num: $#
echo '==========$*=========='
echo all param: $*
echo '==========$@=========='
echo all param : $@
执行
bash parameter.sh abc def
条件判断
语法格式
- test condition
- [ condition ],condition表达式前后有空格
- 整数之间的比较: -eq -ne -lt le -gt -ge
- 文件权限判断: -r -w -x
- 文件类型判断: -e 存在 -f 存在且是file -d存在且是文件夹directory
&&
并且 ||
或者
IF语句
if [ $1 -lt 18 ]
then
echo "less then 18"
elif [ $1 -lt 35 ]
then
echo "less then 35"
else
echo "else"
fi
CASE语句
case $1 in
1)
echo "1"
;;
2)
echo 2
;;
*)
echo else
esac
FOR循环
两种写法
sum=0
for ((i=0;i<=$1;i++))
do
sum=$[ sum + i ]
done
echo $sum
#!/bin/bash
sum=0
for i in {1..100}
do
sum=$[ sum + i ]
done
echo $sum
WHILE循环
a=1
sum2=0
while (($a <= $1))
do
# sum2=$[ sum2 + a ]
# a=$[a+1]
let sum2+=a
let a++
done
echo $sum2
read读取控制台输入
read (选项) (变量名)
选项: -p: 提示语 -t:指定读取值等待时间(秒),不加-t一直等待
#!/bin/bash
read -t 10 -p "please input: " name
echo "input: $name"
函数
系统函数
#输出文件名read_test
basename /home/vmware/scripts/read_test.sh .sh
#获取路径
dirname /home/vmware/scripts/read_test.sh
自定义函数
#!/bin/bash
function add
{
s=$[ $1 + $2 ]
echo $s
}
read -p "please input first numer: " a
read -p "please input second numer: " b
sum=$(add $a $b)
echo "add: "$sum
echo $[$sum * $sum]
综合案例,归档文件
!/bin/bash
if [ $# -eq 1 ]
then
echo "1 parameter"
else
echo "parameter error"
exit
fi
if [ -d $1 ]
then
echo "this is a directory"
else
echo "this is not a directory"
exit
fi
echo
DIR_NAME=$(basename $1)
echo "DIR_NAME: "$DIR_NAME
DIR_PATH=$(cd $(dirname $1);pwd)
echo "DIR_PATH: "$DIR_PATH
DATE=$(date +%y%m%d)
echo "DATE: "$DATE
FILE_NAME=daily_${DIR_NAME}_${DATE}.tar.gz
echo "FILE_NAME: " $FILE_NAME
DEST=${DIR_PATH}/daily/${FILE_NAME}
echo "DEST : " $DEST
tar -czf $DEST $DIR_PATH/$DIR_NAME
if [ $? -eq 0 ]
then
echo "success!"
else
echo "fail!"
fi
exit
正则表达式
规则
^
以什么开头$
以什么结束.
一个任意字符*
字符出现任意次.*
匹配任意字符[]
字符区间,[a-z],[1-9]\
转义字符,'\$'
文本处理工具
cut
cut [参数] filename
- -f,列号 提取第几列
- -d,分隔符,按照指定分隔符分割列,默认制表符’\t’
- -c,按字符进行切割,后加n 表示第几列
echo $PATH | cut -d ":" -f -2
awk
awk [选项] ‘/pattern1/{action1} /pattern2/{action2}’ filename
- -F 指定输入文件分隔符
- -v 赋值一个用户自定义变量
#输出passwd 文件中root开头 暗中:分割 输出第7行
cat /etc/passwd | awk -F ":" '/^root/{print $7}'
#获取的值加上i
cat /etc/passwd | awk -v i=10 -F ":" '{print $3+i}'
awk内置变量
- FILENAME: 文件名
- NR: 已读的记录数(行号)
- NF: 切割后,列的个数
awk -F ":" '{print "filename: "FILENAME " NR:"NR " NF:"NF}' /etc/passwd
综合案例,发送消息
#!/bin/bash
#查看用户是否登录
#-i 忽略大小写, -m 1 提取第一行
login_user=$(who | grep -i -m 1 $1 | awk '{print $1}')
if [ -z $login_user ]
then
echo "$1 用户当前不在线!"
echo "请稍后再试,脚本退出"
exit
fi
#查看用户是否开启消息功能
is_allowd=$(who -T | grep -i -m 1 $1 | awk '{print $2}')
if [ $is_allowd != "+" ]
then
echo "$1 用户未开启消息功能"
echo "脚本退出"
exit
fi
#判断是否有传入需要发送的消息
if [ -z $2 ]
then
echo "需要发送的消息未传入,脚本退出"
exit
fi
#从参数中获取需要发送的消息
whole_msg=$(echo $* | cut -d " " -f 2-)
# 获取用户登录的终端
user_terminal=$(who | grep -i -m 1 $1 | awk '{print $2}')
#写入要发送的消息
echo $whole_msg | write $login_user $user_terminal
if [ $? != 0 ]
then
echo "发送失败"
else
echo "发送成功"
fi
exit
调用
bash send_msg.sh root hello root