1.Shell概述
1.1为什么要学shell
1.看懂运维人员编写的shell脚本
2.偶尔会编写一些简单的shell程序来管理集群,提高开发效率
1.2 Shell介于外层应用和LInux内核之间;用来操作Linux内核;
Shell是一个命令行解释器,它接收应用程序用户命令,然后调用操作系统内核;
Shell还是一个功能强大的编程语言,易编写,好调试,灵活。
2.Shell解析器
sudo vim /etc/shells
上述简单可见6种;
常用sh , bash
如下图所示,sh软连接到bash
软连接和硬链接区别?
系统默认的是bash
3.Shell脚本入门
3.1脚本格式
#!/bin/bash 开头(指定解析器)
3.2需求案例:创建一个脚本输出 helloworld
写一个脚本
#!/bin/bash
echo “helloworld”
[root@192 temp]# vim test.sh
[root@192 temp]# ll
总用量 4
-rw-r--r--. 1 root root 30 4月 23 20:54 test.sh
[root@192 temp]# sudo chmod 777 test.sh
[root@192 temp]# ll
总用量 4
-rwxrwxrwx. 1 root root 30 4月 23 20:54 test.sh
[root@192 temp]# ./test.sh
helloworld
执行脚本的三种方式
但是有可能
原来sh,bash解析器解析,是将脚本放到shell解析器内部进行解析,不需要权限,
但是./hell.sh 是自己调用自己,脚本需要自己执行,当前文件当然没有执行权限;
4.Shell中的变量
需求在/home/atguigu/目录下创建一个banzhang.txt,在banzhang.txt文件中增加“I love cls”。
要点:
- 脚本创建文件夹 ,习惯用vim,但是脚本种不能使用,因此脚本创建文件 touch banzhang.txt
- 脚本写入 touch “***” >> banzhang.txt
4.1系统变量
常见系统变量
H O M E 、 HOME、 HOME、PWD、 S H E L L 、 SHELL、 SHELL、USER等
方便我们找到某一个量,家用户,路径,等
$HOME #未来在使用JAVA_HOME HADOOP_HOME 等都需要定义
4.2自定义变量
4.2.1自定变量
注意:=左右不要有空格
4.2.2撤销变量
unset A
4.2.3声明静态变量
readonly 变量
只读变量,不能unset,想要unset必须当虚拟机重启即可;
4.2.4 定义变量规则
(1)变量名称可以由字母、数字和下划线组成,**但是不能以数字开头,环境变量名建议大写。**JAVA_HOME
(2)等号两侧不能有空格
(3)在bash中,变量默认类型都是字符串类型,无法直接进行数值运算。
(4)变量的值如果有空格,需要使用双引号或单引号括起来。
4.2.5将变量定义为全局变量供其他脚本使用
export D=mm
特殊变量
$n(功能描述:n为数字,$0代表该脚本名称,$1- 9 代表第一到第九个参数,十以上的参数,十以上的参数需要用大括号包含,如 9代表第一到第九个参数,十以上的参数,十以上的参数需要用大括号包含,如 9代表第一到第九个参数,十以上的参数,十以上的参数需要用大括号包含,如{10})
也就是脚本接受参数的写法$n $0表示自身,其他从1-9表示窗口接收的参数索引;
上图$2接收banzhang 2号参数 $3接收 xihuan$4接收mm
接收参数的一种形式,从命令行输入然后接收作为变量;
$# (功能描述:获取所有输入参数个数,常用于循环)。
∗ (功能描述:这个变量代表命令行中所有的参数, * (功能描述:这个变量代表命令行中所有的参数, ∗(功能描述:这个变量代表命令行中所有的参数,*把所有的参数看成一个整体)
@ (功能描述:这个变量也代表命令行中所有的参数,不过 @ (功能描述:这个变量也代表命令行中所有的参数,不过 @(功能描述:这个变量也代表命令行中所有的参数,不过@把每个参数区分对待)
[atguigu@hadoop101 datas]$ vim parameter.sh
#!/bin/bash
echo "$0 $1 $2"
echo $#
echo $*
echo $@
[atguigu@hadoop101 datas]$ bash parameter.sh 1 2 3
parameter.sh 1 2
3
1 2 3
1 2 3
$?(功能描述:最后一次执行的命令的返回状态。如果这个变量的值为0,证明上一个命令正确执行;如果这个变量的值为非0(具体是哪个数,由命令自己来决定),则证明上一个命令执行不正确了。)
5.运算符
基本语法:
(1)“ ( ( 运算式 ) ) ”或“ ((运算式))”或“ ((运算式))”或“[运算式]”
(2)expr + , - , *, /, % 加,减,乘,除,取余
注意:expr运算符间要有空格
1.计算3+2的值
2.计算计算(2+3)X4的值
采用$[运算式]方式
6.条件判断
1.基本语法
[ condition ](注意condition前后要有空格)
注意:条件非空即为true,[ atguigu ]返回true,[] 返回false。
- 常用判断条件
(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)
案例实操
1.判断23是否大于22
2.判断某个文件是否有写权限
3.判断某个文件是否存在
4.多条件判断 shells是否存在,是否可读
7.流程控制*
7.1 if 判断
1.基本语法
if [ 条件判断式 ];then
程序
fi
或者
if [ 条件判断式 ]
then
**程序**
fi
注意事项:
(1)[ 条件判断式 ],中括号和条件判断式之间必须有空格
(2)if后要有空格
案例实操
1.输入一个数字,如果是1,则输出banzhang zhen shuai,如果是2,则输出cls zhen mei,如果是其它,什么也不输出。
注意事项:
接收字符串匹配相等需要用 -eq
condition前后需要有空格
条件判断中间要有空格 $1 -eq 1
7.2 case 语句
1.基本语法
case $变量名 in
“值1”)
如果变量的值等于值1,则执行程序1
;;
“值2”)
如果变量的值等于值2,则执行程序2
;;
…省略其他分支…
*)
如果变量的值都不是以上的值,则执行此程序
;;
esac
注意事项:
1) case行尾必须为单词“in”,每一个模式匹配必须以右括号“)”结束。
2) 双分号“**;;**”表示命令序列结束,相当于java中的break。
3) 最后的“*)”表示默认模式,相当于java中的default。
案例实操
1.输入一个数字,如果是1,则输出banzhang,如果是2,则输出cls,如果是其它
case接收一个数字然后写in
接收匹配案例使用 1),2),3),*) 匹配1,2,3和其他
第一个匹配结束后需要双分号结束;;
最终结束符caase的反向拼写结束esac
7.3 for 循环
1.基本语法1
for (( 初始值;循环控制条件;变量变化 ))
do
程序
done
与Java的区别
条件那一栏是双括号,但是里面内容一样
原来的大括号{} 变为现在的do,done
中间的一样;
案例
1.从1加到100
中间的程序
s=$[$s+$i] #表示取出s和i的值进行相加后的结果赋值给变量s
s=expr $s + $i 这是另一种写法
2.基本语法2
for 变量 in 值1 值2 值3…
do
程序
done
案例实操
1.打印所有输入参数
$*表示所有参数输入 的
echo "" 内部也可以使用$i 进行取值操作
观察输出结果;
若带“”的话,$* 会将你输入的所有参数当成一个整体,循环仅执行1次
而带“”的$@ 还是每一次都接收你输入的单个参数,循环执行多次;
7.4 while 循环
1.基本语法
while [ 条件判断式 ]
do
程序
done
从1加到100
此行代码少了echo,请补上:
echo $s
8.read读取控制台输入
基本语法
read(选项)(参数)
选项:
-p:指定读取值时的提示符;
-t:指定读取值时等待的时间(秒)。
参数
变量:指定读取值的变量名
读取控制台的值,赋值给一个变量
案例:提示7秒内,读取控制台输入的名称
#!/bin/bash
read -t 7 -p "Enter your name in 7 seconds " NAME
echo $NAME
最终输入的变量,是需要赋值给NAME的
注意:NAME直接在read指令种定义的变量;
9.函数
9.1系统函数
1.basename基本语法
basename [string / pathname] [suffix] (功能描述:basename命令会删掉所有的前缀包括最后一个(‘/’)字符,然后将字符串显示出来。
选项:
suffix为后缀,如果suffix被指定了,basename会将pathname或string中的suffix去掉。
例子:获取输入路径的basename
先使用条件判断banzhang.txt不存在
使用basename获取输入路径的basename;不存在的也可获取;
#请注意
$? 也是需要echo的,因为其具有返回值;
也就是说加上后缀的话,会将后缀进行匹配然后干掉后输出;
2.dirname基本语法
dirname 文件绝对路径 (功能描述:从给定的包含绝对路径的文件名中去除文件名(非目录的部分),然后返回剩下的路径(目录的部分))
小结:是返回路径的,与basename相反
9.2自定义函数
基本语法
[ function ] funname[()]
{
Action;
[return int;] #return一般不采用此方式,一般采用$?方式返回是否执行成功
}
funname
经验技巧
1.必须先声明函数,然后再调用,shell是逐行执行,不会向其他语言一样先编译。和python都是解释型语言;
2.返回值只能通过$?系统变量获得,可以显示加:return 返回,如果不加,将以最后一条命令运行结果,作为返回值,return后跟数值n(0-255)
案例:计算两个输入参数的和
注意点:read函数 -t -p严格按先后顺序,先-t后-p
调用函数的实参无括号
定义函数无形参
10.Shell工具***
开发中重点中重点
cut
cut的工作就是“剪”,具体的说就是在文件中负责剪切数据用的。cut 命令从文件的每一行剪切字节、字符和字段并将这些字节、字符和字段输出
cut [选项参数] filename
选项参数 | 功能 |
---|---|
-f | 列号,提取第几列 |
-d | 分隔符,按照指定分隔符分割列 |
案例
数据准备
[atguigu@hadoop101 datas]$ touch cut.txt
[atguigu@hadoop101 datas]$ vim cut.txt
dong shen
guan zhen
wo wo
lai lai
le le
切割cut.txt的第一列
小结:
cut命令只能按列进行切割;
命令进行指定;先制定切割 方法-d 后指定 切割得到哪一列 -f
他会按照空格数严格切分;
获取guan zhen 一行种的guan
方法:先获取某一行,使用管道符;然后进行cut之间用|连接
获取系统PATH变量值,第二个":"开始后的所有路径
小结:cut -f选取列的时候支持,号分割选取多列
小结:
1.切割-d 可以没有分号
2.-f 从第二列往后,-f 2-
3.不支持*号进行计数
切割ifconfig输出内容,切割出ip地址;
技巧grep可以i进行初步过滤
小结:cut只能切割单个字符,多个字符不支持,其次切割玩可以继续切割
用途,切割大量日志文件种的ip
sed
sed是一种流编辑器,它一次处理一行内容。处理时,把当前处理的行存储在临时缓冲区中,称为“模式空间”,接着用sed命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕。接着处理下一行,这样不断重复,直到文件末尾。文件内容并没有改变,除非你使用重定向存储输出。
基本用法
sed [选项参数] ‘command’ filename
选项参数 |
---|
-e 直接在指令列模式上进行sed的动作编辑 |
命令 | 功能描述 |
---|---|
a | 新增,a的后面可以接字串,在下一行出现 |
d | 删除 |
s | 查找并替换 |
案例操作
数据准备
[atguigu@hadoop102 datas]$ touch sed.txt
[atguigu@hadoop102 datas]$ vim sed.txt
dong shen
guan zhen
wo wo
lai lai
le le
(1)将“mei nv”这个单词插入到sed.txt第二行下,打印。
小结:
命令操作sed需要加""; “2a mei nv” 表示源文件第2行添加mei nv
但是源文件内容不发生改变
(2)删除文件中所有包含wo的行
(3)将sed.txt文件中wo替换为ni
g表示全局,不加表示第一个操作
替换,删除操作使用/ 表示
替换前面加s
删除后面加d
(4)将sed.txt文件中的第二行删除并将wo替换为ni
多个指令进行执行,
每执行一个指令,前面加上-e 即可
awk
一个强大的文本分析工具,把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行分析处理。
和cut很相似,但是处理规则不同
基本用法
awk [选项参数] ‘pattern1{action1} pattern2{action2}…’ filename
pattern:表示AWK在数据中查找的内容,就是匹配模式
action:在找到匹配内容时所执行的一系列命令
选项参数 | 功能 |
---|---|
-F | 指定输入文件折分隔符 |
-v | 赋值一个用户定义变量 |
实际操作
sudo cp /etc/passwd ./
(1)搜索passwd文件以root关键字开头的所有行,并输出该行的第7列。
小结:
匹配与cut不同,指定分隔符使用—F
正则表达式需要用单引号引起来 ,内部需要打印,print
{print $7} #表示打印第7列
最终需要指定文件
(2)搜索passwd文件以root关键字开头的所有行,并输出该行的第1列和第7列,中间以“,”号分割。
中间以逗号连接","
(3)只显示/etc/passwd的第一列和第七列,以逗号分割,且在所有行前面添加列名user,shell在最后一行添加"dahaige,/bin/zuishuai"。
请注意:打印第一列,第七列不需要 “”
整体逻辑:BEGIN打印---
中间 打印第一列第七列
END末尾打印---
指令不改变源文件内容
(4)将passwd文件中的用户id增加数值1并输出
此处比较特殊,他是直接拿i=1进行赋值了,不需要进行$取值操作
-F 切割
-v 定义一个变量
内置变量
变量 | 说明 |
---|---|
FILENAME | 文件名 |
NR | 切割后的行数 |
NF | 切割后有几个列 |
使用awk进行获取ip地址
sort
将文件进行排序,并将结果标准输出
选项 | 说明 |
---|---|
-n | 依照数值的大小排序 |
-r | 以相反的顺序来排序 |
-t | 设置排序时所用的分隔字符 |
-k | 指定需要排序的列 |
案例
数据准备
vim sort.sh
bb:40:5.4
bd:20:4.2
xz:50:2.3
cls:10:3.5
ss:30:1.6
(1)按照“:”分割后的第三列倒序排序。
-t指定切法
-n数字排序
-r倒叙
-k指定列
最终指定文本
11.企业面试题*
问题1:使用Linux命令查询file1中空行所在的行号
awk '/^$ {print NR}' file1.txt
难点:空行正则表达式:就是 ^$
空行的使用场景:日志种,突然冒出大段空行,那么一定会存在异常,得会调用;
null
404
500等数据清洗 -- ETL
问题2:有文件chengji.txt内容如下:
张三 40
李四 50
王五 60
使用Linux命令计算第二列的和并输出
cat chengji.txt | awk -F " " '{sum+=$2} END{print sum}'
逻辑思路:先将所有的第二列的值进行查询,然后正则将其相加{sum+=$2} #也就是将第二列数据相加
最终打印sum
问题3:Shell脚本里如何检查一个文件是否存在?如果不存在该如何处理?
#!/bin/bash
if [ -f file.txt ]; then
echo "文件存在!"
else
echo "文件不存在!"
fi
-f 文件存在并且是一个常规的文件(file)
-e 文件存在(existence)
问题4.用shell写一个脚本,对文本中无序的一列数字排序
sort -n test.txt|awk '{a+=$0;print $0}END{print "SUM"=a}'
问题5:请用shell脚本写出查找当前文件夹(/home)下所有的文本文件内容中包含有字符”shen”的文件名称
grep -r "shen" /home | cut -d ":" -f 1