感谢尚硅谷!!!
1.什么是shell
-
对于大数据来说,初期我们会写一些简单的脚本如群起群停脚本来使用,初学不用太过深入
2.第一个脚本
#!bin/bash #解释器 echo "Hello world!!"
3.变量
-
自定义变量
/* 1)基本语法 (1)定义变量:变量=值 (2)撤销变量:unset 变量 (3)声明静态变量:readonly变量,注意:不能unset 断开重连会刷新(都是临时的变量) 2)变量定义规则 (1)变量名称可以由字母、数字和下划线组成,但是不能以数字开头,环境变量名建议大写。 (2)等号两侧不能有空格 (3)在bash中,变量默认类型都是字符串类型,无法直接进行数值运算。 (4)变量的值如果有空格,需要使用双引号或单引号括起来。 */
-
注意事项:
#可把变量提升为全局环境变量,可供其他Shell程序使用 export 变量名 [atguigu@hadoop101 datas] vim helloworld.sh 在helloworld.sh文件中增加echo $B #!/bin/bash echo "helloworld" echo $B [atguigu@hadoop101 datas] ./helloworld.sh Helloworld 发现并没有打印输出变量B的值。 [atguigu@hadoop101 datas] export B [atguigu@hadoop101 datas] ./helloworld.sh helloworld 2
-
特殊变量
$n (1)基本语法
$n (功能描述:n为数字,$0代表该脚本名称,$1-$9代表第一到第九个参数,十以上的参数,十以上的参数需要用大括号包含,如${10})
[atguigu@hadoop101 datas] touch parameter.sh [atguigu@hadoop101 datas] vim parameter.sh #!/bin/bash echo "$0 $1 $2" [atguigu@hadoop101 datas] chmod 777 parameter.sh [atguigu@hadoop101 datas] ./parameter.sh cls xz ./parameter.sh cls xz
$#(1)基本语法
$# (功能描述:获取所有输入参数个数(3 5 6 ),常用于循环)。
atguigu@hadoop101 datas] vim parameter.sh #!/bin/bash echo "$0 $1 $2" echo "=========$#=======" #此句中的$#会被解析,也就是说,如果你传了两个参数这里会显示2 echo '=========$#=======' #如果不想被解析使用单引号!!!对特殊变量是最好使用单引号,除非想被解析 echo $# [atguigu@hadoop101 datas] chmod 777 parameter.sh [atguigu@hadoop101 datas] ./parameter.sh cls xz parameter.sh cls xz 2
$*、$@(1)基本语法
$* (功能描述:这个变量代表命令行中所有的参数,$*把所有的参数看成一个整体)
$@ (功能描述:这个变量也代表命令行中所有的参数,不过$@把每个参数区分对待)
注意:如果想让$*和$@ 体现区别必须用双引号括起来才生效
//具体什么区别呢?大约也就是在for循环中,$*只能循环一次 $@却能循环为传入参数的个数
[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
$?(1)基本语法
$?如果返回值为0则代表执行正确,否则反之
判断helloworld.sh脚本是否正确执行 [atguigu@hadoop101 datas] ./helloworld.sh hello world [atguigu@hadoop101 datas] echo $? 0
4.运算符
-
基本语法
$((运算式)) 或 $[运算式] 前者对于复杂式可能会不是那么简便,建议用后者
5.条件判断
-
基本语法
-
test condition
-
[ condition ](注意condition前后要有空格)
注意:条件非空即为true,[ atguigu ]返回true,[] 返回false。建议用后者
-
-
常用判断条件(注意,在shell语句中不可以直接使用大于号小于号)
-
两个整数之间比较
== 字符串比较
-lt 小于(less than) -le 小于等于(less equal)
-eq 等于(equal) -gt 大于(greater than)
-ge 大于等于(greater equal) -ne 不等于(Not equal)
-
按照文件权限进行判断
-r 有读的权限(read) -w 有写的权限(write)
-x 有执行的权限(execute)
-
按照文件类型进行判断
-f 文件存在并且是一个常规的文件(file)
-e 文件存在(existence) -d 文件存在并是一个目录(directory)
-
23是否大于等于22 [atguigu@hadoop101 datas]$ [ 23 -ge 22 ] [atguigu@hadoop101 datas]$ echo $? 0 helloworld.sh是否具有写权限 [atguigu@hadoop101 datas]$ [ -w helloworld.sh ] [atguigu@hadoop101 datas]$ echo $? 0 /home/atguigu/cls.txt目录中的文件是否存在 [atguigu@hadoop101 datas]$ [ -e /home/atguigu/cls.txt ] [atguigu@hadoop101 datas]$ echo $? 1
6.流程控制
-
if判断
if [ 条件判断式 ] then 程序 elif [ 条件判断式 ] then 程序 else 程序 fi 注意事项: (1)[ 条件判断式 ],中括号和条件判断式之间必须有空格 (2)if后要有空格
-
case语句
case $变量名 in "值1") 如果变量的值等于值1,则执行程序1 ;; "值2") 如果变量的值等于值2,则执行程序2 ;; …省略其他分支… *) 如果变量的值都不是以上的值,则执行此程序 ;; esac 注意事项: (1)case行尾必须为单词“in”,每一个模式匹配必须以右括号“)”结束。 (2)双分号“;;”表示命令序列结束,相当于java中的break。 (3)最后的“*)”表示默认模式,相当于java中的default。
-
for循环
注意:在for循环中可以使用大于号小于号之类的
//方法一: for (( 初始值;循环控制条件;变量变化 )) do 程序 done //方法二: for 变量 in 值1 值2 值3… do 程序 done
例子:
#方法一: #!/bin/bash s=0 for((i=0;i<=100;i++)) do s=$[$s+$i] done echo $s #!/bin/bash #重点来了,在上文我们说过$*会看作一个整体也就是循环一次, #而下述内容起始还是会分开,也就是循环你传入参数个数的次数 #但如果你加上引号的话,不管你传入几个参数都只会循环一次,一次性把所有参数输出 for i in $* do echo "你好 -- $i " done
-
while循环
注意:在while中又恢复到shell规则里,也就是说不能在使用大于号小于号啦!!!
while [ 条件判断式 ] do 程序 done
#!/bin/bash #从1加到100 s=0 i=1 while [ $i -le 100 ] do s=$[$s+$i] i=$[$i+1] done echo $s
7.函数
-
系统函数
1.basename basename /root/shell/case.sh 作用:会自动获得case.sh 也即是说,传入一个路径会自动获得它最后的文件名 2.dirname dirname /root/shell/case.sh 作用:会自动获得/root/shell 也就是说会自动获得它的文件路径,除文件名外的 和basename函数搭配正好可以还原成文件绝对路径
-
自定义函数
#定义函数 [ function ] funname[()] #括号里什么也不传 { Action; [return int;] #只能返回0-255 } #调用函数 funname 注意: (1)必须在调用函数地方之前,先声明函数,shell脚本是逐行运行。不会像其它语言一样先编译。 (2)函数返回值,只能通过$?系统变量获得,可以显示加:return返回,如果不加,将以最后一条命令运行结果,作为返回值。return后跟数值n(0-255) (3)在shell脚本中对于数值运算还是比较少的,在函数里面写业务逻辑 例如: s=0 function sum() { s=$[ $1 + $2 ]; return $s; } sum 1 2 echo "和为:" $? #注意注意
8.正则表达式
-
常规匹配
一串不包含特殊字符的正则表达式匹配它自己,例如:
[atguigu@hadoop102 datas]$ cat /etc/passwd | grep atguigu
就会匹配所有包含atguigu的行
-
常用特殊字符
-
特殊字符:^
^ 匹配一行的开头,例如:
[atguigu@hadoop102 datas]$ cat /etc/passwd | grep ^a
会匹配出所有以a开头的行
-
特殊字符:$
$ 匹配一行的结束,例如
[atguigu@hadoop102 datas]$ cat /etc/passwd | grep t$
会匹配出所有以t结尾的行
思考:^$ 匹配什么? 答:匹配空行
-
特殊字符:.
. 匹配一个任意的字符,例如
[atguigu@hadoop102 datas]$ cat /etc/passwd | grep r..t
会匹配包含rabt,rbbt,rxdt,root等的所有行
-
特殊字符:*
* 不单独使用,他和左边第一个字符连用,表示匹配上一个字符0次或多次,例如
[atguigu@hadoop102 datas]$ cat /etc/passwd | grep ro*t
会匹配rt, rot, root, rooot, roooot等所有行
思考:.* 匹配什么? 答:匹配所有
-
特殊字符:[ ]
[ ] 表示匹配某个范围内的一个字符,例如
[6,8]------匹配6或者8
[a-z]------匹配一个a-z之间的字符
[a-z]*-----匹配任意字母字符串
[a-c, e-f]-匹配a-c或者e-f之间的任意字符
[atguigu@hadoop102 datas]$ cat /etc/passwd | grep r[a,b,c]*t
会匹配rat, rbt, rabt, rbact等等所有行
-
特殊字符:\
\ 表示转义,并不会单独使用。由于所有特殊字符都有其特定匹配模式,当我们想匹配某一特殊字符本身时(例如,我想找出所有包含 '$' 的行),就会碰到困难。此时我们就要将转义字符和特殊字符连用,来表示特殊字符本身,例如
[atguigu@hadoop102 datas]$ cat /etc/passwd | grep a$b
注意:直接匹配 $ 字符,需要进行转义并且加上单引号
就会匹配所有包含 a$b 的行。
9.Shell工具
把一些杂乱的数据用shell工具切割进行规则化,用于清洗数据
-
cut 不支持多个字符
1)基本用法 cut [选项参数] filename 说明:默认分隔符是制表符 2)选项参数说明 选项参数 功能 -f 列号,提取第几列 -d 分隔符,按照指定分隔符分割列 -c 指定具体的字符
例子
(1)数据准备 [atguigu@hadoop101 datas]$ vim cut.txt dong shen guan zhen wo wo #注意有多个空格 lai lai le le (2)切割cut.txt第一列 [atguigu@hadoop101 datas]$ cut -d " " -f 1 cut.txt dong guan wo lai le (3)切割cut.txt第二、三列 [atguigu@hadoop101 datas]$ cut -d " " -f 2,3 cut.txt shen zhen wo #注意前面有空格 lai le (4)切割cut.txt第二及第二列后面所有列 [atguigu@hadoop101 datas]$ cut -d " " -f 2- cut.txt shen zhen wo #注意前面有空格 lai le (5)在cut.txt文件中切割出guan #放到 | 管道里面进行相应的切割 [atguigu@hadoop101 datas]$ cat cut.txt | grep "guan" | cut -d " " -f 1 guan
-
awk
一个强大的文本分析工具,把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行分析处理。且支持多个字符
1)基本用法 awk [选项参数] ‘pattern1{action1} pattern2{action2}...’ filename pattern:表示AWK在数据中查找的内容,就是匹配模式 简单来说就是正则表达式 action:在找到匹配内容时所执行的一系列命令 2)选项参数说明 选项参数 功能 -F 指定输入文件折分隔符 -v 赋值一个用户定义变量
#例子 awk -F: '/^root/{print $7}' passwd #正则一般在/中间写/ (1)只显示/etc/passwd的第一列和第七列,以逗号分割,且在所有行前面添加列名user,shell在最后一行添加"dahaige,/bin/zuishuai"。 [atguigu@hadoop102 datas]$ awk -F : 'BEGIN{print "user, shell"} {print $1","$7} END{print "dahaige,/bin/zuishuai"}' passwd user, shell root,/bin/bash bin,/sbin/nologin 。。。 atguigu,/bin/bash dahaige,/bin/zuishuai 注意:BEGIN 在所有数据读取行之前执行;END 在所有数据执行之后执行。 (2)将passwd文件中的用户id增加数值1并输出 # -v i为自定义变量 [atguigu@hadoop102 datas]$ awk -v i=1 -F: '{print $3+i}' passwd 1 2 3 4
awk的内置变量
变量 说明 FILENAME 文件名 NR 已读的记录数(行数) NF 浏览记录的域的个数(切割后,列的个数) -
sort
sort命令是在Linux里非常有用,它将文件进行排序,并将排序结果标准输出。
1)基本语法
sort(选项)(参数)
选项 说明 -n 依照数值的大小排序 -r 以相反的顺序来排序 -t 设置排序时所用的分隔字符 -k 指定需要排序的列 参数:指定待排序的文件列表
例子
(1)数据准备 [atguigu@hadoop102 datas]$ touch sort.sh [atguigu@hadoop102 datas]$ vim sort.sh bb:40:5.4 bd:20:4.2 xz:50:2.3 cls:10:3.5 ss:30:1.6 (2)按照“:”分割后的第三列倒序排序。 [atguigu@hadoop102 datas]$ sort -t : -nrk 3 sort.sh bb:40:5.4 bd:20:4.2 cls:10:3.5 xz:50:2.3 ss:30:1.6
-