目录
1 概述
# shell 是一个命令行的解释器,它接收应用程序/用户命令,然后调用操作系统内核
1.1 格式
脚本以#!/bin/bash开头(指定解析器)
创建一个脚本1.sh
输出hello world!!!
1.2 执行脚本方式
第一种:bash或者sh ./1.sh(这种方式不用赋予脚本执行权限)
第二种方式:
第三种方式
前两种方式相当于在当前shell中启动了一个子shell,在这个子shell中执行脚本,脚本内容结束关闭子shell回到父shell;第三种方式就是在当前shell中执行脚本
开子shell与不开子shell最大的区别就在于,环境变量的继承关系,在子shell中设置的当前变量,父shell是不可见的
2 变量
2.1 系统变量
常用系统变量:
$HOME $PWD $SHELL $USER等
查看环境变量
# echo $HOME或者 pritnenv HOME
查看所有的系统全局变量:env或者printenv
# set 查看所有变量
2.2 自定义变量
基本语法:
定义变量:变量名=变量值 “=”前后无空格
撤销变量:unset 变量名
这种方式定义的变量是局部变量
定义全局变量:export
但是,如果在子shell中改变变量的值,不会影响到父shell中变量的值
接下来新定义一个局部变量c ,并赋值"hello world"
脚本内容:
./运行结果
#bash/sh+脚本名或者是./+脚本名,其实是在当前shell中开启了一个子shell,去子shell里执行脚本,而变量c作为一个局部变量,在子shell中是没有被定义的,所以就输出不了变量c
# source 运行结果
因为source 或者 “.”的方式就是在当前shell中执行,无关是全局变量还是局部变量
声明静态变量:readonly变量名,不能unset
变量定义规则
1、变量名称可以由字母、数字和下划线组成,但是不能以数字开头,环境变量建议大写
2、等号两侧不能有空格
3、在bash中,变量默认类型都是字符串型,无法直接进行数值运算
4、变量的值如果由空格,需要使用双引号或单引号括起来
将脚本放到/bin/目录下,直接输入脚本名称执行
环境变量$PATH
2.3 特殊变量
2.3.1 $n
功能描述:n为数字,$0代表该脚本的名称,$1-$9代表第一到第九个参数,十以上的参数需要用大括号包含,如${10}
2.3.2 $#
功能描述:获取所有输入参数个数,常用于循环,判断参数的个数是否正确以及加强脚本的健壮性
2.3.3 $*、$@
$*:这个变量代表命令行中所有的参数,$*把所有的参数看成一个整体
$@:这个变量也代表命令行中所有的参数,不过$@把每个参数区分对待
2.3.4 $?
功能描述:最后一次执行命令的返回状态。如果这个变量的值为0,证明上一个命令正确执行;如果这个变量的值非0(具体是什么数字,由命令自己决定),则证明上一个命令没有正确执行。
3 运算符
3.1 expr
3.2 $((运算式))或者$[运算式]
4 条件判断
基本语法
4.1 test condition
4.2 [condition]
condition前后要有空格
注意:条件非空即为true,[123]返回true, [ ]返回false
4.3 常用判断条件
4.3.1 两个整数之间比较
-eq 等于
-ne 不等于
-lt 小于
-le小于等于
-gt 大于
-ge 大于等于
4.3.2 字符串比较
如果是字符串之间的比较,用等号“=”判断相等;“!=”判断不等
4.4 按照文件权限进行判断
-r:读
-w:写
-x:执行
4.5 按照文件类型进行判断
-e:文件存在
-f:文件存在并且是一个常规的文件
-d:文件存在并且是一个目录
4.6 多条件判断
&&表示前一条命令执行成功时,才执行后一条命令,||表示上一条命令执行失败后,才执行吓一跳命令
5 流程控制
5.1 if 判断
# if 判断
基本语法
5.1.1 单分支
if [条件判断式];then
程序
fi
或者
if [条件判断式]
then
程序
fi
5.1.2 多分支
if [条件判断]
then
程序
elif [条件判断]
then
程序
else
then
程序
5.2 case 语句
# case 语句
基本语法
case $变量名 in
x)
变量的值等于x,执行程序1
;;
y)
变量的值等于y,执行程序2
;;
*)
如果变量的值都不是以上的值,则执行此程序
;;
注意事项:
1、case行尾必须为单词"in" ,每一个模式匹配以右括号结束
2、双分号表示命令序列结束,相当于java中的break
3、最后*),表示默认,相当于java中的default
5.3 for 循环
# for循环
5.3.1 基本语法1
# for ((初始值;循环控制条件;变量变化))
do
程序
done
九九乘法表
5.3.2 基本语法2
# for 变量 in 值1 值2 值3
do
程序
done
5.4 while 循环
# while 循环
基本语法
# while [条件判断]
do
程序
done
# let
第6章 read 读取控制台输入
基本语法
# read (选项) (参数)
选项:
-p:指定读取值时的提示符;
-t:指定读取值时等待的时间(秒),不加表示一致等待
参数:
变量:指定读取值的变量名
第7章 函数
7.1 系统函数
7.1.1 basename
基本语法:
# basename [string/pathname] [suffix]
功能描述:basename 命令会删掉所有的前缀包括最后一个 “/”字符,然后讲字符串显示出来。
可以理解为取路径中的文件名
选项:
suffix 为后缀,如果suffix被指定了,basename会将pathname或string中的suffix去掉
7.1.2 dirname
基本语法
# dirname 文件绝对路径
功能描述
从给定的包含绝对路径的文件名中去除文件名,保留路径部分
可以理解为读取文件的绝对路径
输出执行脚本的绝对路径
7.2 自定义函数
基本语法
# function 函数名()
{
Action;
return int;
}
经验技巧
1、必须要在调用函数之前,先声明函数,shell脚本时逐行运行。不会向其它语言一样先编译。
2、函数返回值,只能通过$?系统变量获得,可以显示加:return 返回,如果不加,将以最后一条命令运行结果,作为返回值。return后跟数值n(0-255)
练习--猜数字程序
#!/bin/bash
#自定义函数,猜数字程序主要内容
function game()
{
rand=$[$(date +%N | cut -c 1-2 )+1]
read -p "请输入:" x
while [ 1 -lt 2 ]
do
if [ $x -lt $rand ]
then
read -p "往大了猜:" x
elif [ $x -gt $rand ]
then
read -p "往小了猜:" x
else
return 0
fi
done
}
echo "=========Welcome========="
read -p "输入:1、开始游戏;0、退出游戏:" n
case $n in
1)
echo "随机数字1-100已经生成,请开始"
$(game)
if [ $? -eq 0 ];then
echo "恭喜你答对了!"
fi
;;
0)
exit
;;
esac
8 实例练习
8.1 归档文件
实际生产应用中,往往需要对重要数据进行归档备份
需求:实现一个每天对指定目录归档备份的脚本,输入一个目录名称(末尾不带/),将目录下所有文件按天归档保存,并将归档日期附加在归档文件名上,放在/root/archive下。
运行结果
添加定时任务
9 正则表达式
正则表达式使用单个字符串来描述,匹配一系列符合某个语法规则的字符串,在很多文本编辑器里,正则表达式通常被用来检索,替换那些符合某个模式的文本。在Linux中,grep,sed,awk等文本处理工具都支持通过正则表达式进行模式匹配
9.1 常规匹配
一串不包含特殊字符的正则表达式匹配它自己
9.2 常用特殊字符
9.2.1 特殊字符:^
匹配一行的开头
9.2.2 特殊字符:$
匹配一行的结束
9.2.3 特殊字符:.
匹配一个任意的字符,例如
9.2.4 特殊字符:*
不单独使用,他和上一个字符连用,表示匹配上一个字符0次或多次
9.2.5 特殊字符组合查询
9.2.6 字符区间 中括号:[]
[] 表示匹配某个范围内的一个字符
[6,8] 匹配6或者8
[0-9] 匹配任意长度的数字字符串
[a-z] 匹配任意长度的字母字符串
[a-c,e-f] 匹配a-c或者e-f之间的任意字符
9.2.7 特殊字符:\
\表示转义,并不会单独使用。由于所有特殊字符都有其特定匹配模式,当我们想匹配某一特殊字符本身时,就会碰到困难。此时我们就要将转义字符和特殊字符连用,来表示特殊字符本身
10 文本处理工具
10.1 cut
cut的工作就是剪,具体的说就是在文件中负责剪切数据用的。cut命令从文件的每一行剪切字节、字符和字段并将这些字节、字符和字段输出。
基本用法
cut [选项参数] filename
说明:默认分隔符是制表符
选项说明
-f :列号,提取第几列
-d:分隔符,按照指定分隔符分割列,默认是制表符“\t”
-c:按字符进行切割,后加n 表示取第几列
截取IP地址
10.2 awk
一个强大的文本分析工具,把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分在进行分析处理。
基本用法
awk [选项参数] '/pattern1/{action1} /pattern2/{action2}…' filename
pattern:表示awk在数据中查找的内容,就是匹配模式
action:在找到匹配内容时所执行的一系列命令
注意:只有匹配了pattern才会执行action
选项说明
-F:指定输入文件分隔符
-v:赋值一个用户自定义变量
搜索passwd文件以root关键字开头的所有行,并且输出该行第7列
搜索passwd文件以root关键字开头的所有行,并输出改行的第1列和第7列,中间以","号分割
只显示/etc/passwd的第1列和第7列,以逗号分隔,且在所有行前面添加列名user,shell在最后一行添加"dahaige, /bin/zuishuai"
把passwd文件中的用户id增加数值1并输出
awk 内置变量
FILENAME 文件名
NR 已读的记录数(行号)
NF 浏览记录的域的个数(列数)
统计passwd文件名,每行的行号,每行的列数
查询ifconfig命令输出结果中的空行所在的行号
截取IP
11 综合应用案例
发送消息
我们可以利用Linux自带的mesg和write工具,向其它用户发送消息。
需求:实现一个向某个用户快速发送消息的脚本,输入用户名作为第一个参数,后面直接跟要发送的消息。脚本需要检测用户是否登录在系统中、是否打开消息功能,以及当前发送消息是否为空。
# mesg 查看当前用户是否开启消息功能
# mesg n 关闭消息功能
# mesg y 开启消息功能
# who -T 查看登录的用户
# write 用户名 终端名 向指定用户发送消息
脚本: