1 Shell概述
Shell是一个命令行解释器,它接收应用程序、用户命令,然后调用操作系统内核。
Shell还是一个功能相当强大的编程语言,易编写、易调试、灵活性强。
[root@iZlu4gn37663k7Z home]# cat /etc/shells
/bin/sh
/bin/bash
/usr/bin/sh
/usr/bin/bash
[root@iZlu4gn37663k7Z bin]# ll |grep bash
-rwxr-xr-x. 1 root root 964608 Oct 31 2018 bash
lrwxrwxrwx. 1 root root 10 Jul 11 2019 bashbug -> bashbug-64
-rwxr-xr-x. 1 root root 6964 Oct 31 2018 bashbug-64
lrwxrwxrwx. 1 root root 4 Jul 11 2019 sh -> bash
由上可知bash与sh一样,只是个软连接罢了
2 Shell脚本入门
脚本格式
脚本以#!/bin/bash 开头(指定解析器)
第一个 Shell 脚本:helloworld
需求:创建一个 Shell 脚本,输出 helloworld
#!/bin/bash echo "helloworld"
脚本的常用执行方式
第一种:采用 bash 或 sh+脚本的相对路径或绝对路径(不用赋予脚本+x 权限)
sh+脚本的相对路径
sh helloworld.sh
sh+脚本的绝对路径
sh /home/atguigu/datas/helloworld.sh
bash+脚本的相对路径
bash helloworld.sh
bash+脚本的绝对路径
bash /home/atguigu/datas/helloworld.sh
第二种:采用输入脚本的绝对路径或相对路径执行脚本(必须具有可执行权限+x)
首先要赋予 helloworld.sh 脚本的+x 权限
chmod +x helloworld.sh
执行脚本
# 相对路径 ./helloworld.sh # 绝对路径 /home/atguigu/datas/helloworld.sh
注意:第一种执行方法,本质是 bash 解析器帮你执行脚本,所以脚本本身不需要执行权限。
第二种执行方法,本质是脚本需要自己执行,所以需要执行权限。
3 变量
3.1 系统预定义变量
常用系统变量
$HOME、$PWD、$SHELL、$USER
查看系统变量的值
echo $HOME
显示当前 Shell 中所有变量
set
3.2 自定义变量
基本语法
- 定义变量:变量=值;变量=‘值’;变量=“值”(双引号括的东西可以被识别,单引号则是死的、固定的字符串,类似于pyhon的 f'字符串里直接输出{变量}',亦或是 '字符串里直接输出{}'.formath(变量) )
- 撤销变量:unset变量
- 声明静态变量:readonly变量,注意:不能unset
变量定义规则
- 变量名称可以由字母、数字和下划线组成,但是不能以数字开头,环境变量名建议大写
- 等号两侧不能有空格
- 在 bash 中,变量默认类型都是字符串类型,无法直接进行数值运算。
- 变量的值如果有空格,需要使用双引号或单引号括起来。
注意事项
- readonly声明的静态变量,不能 unset
- 在 bash 中,变量默认类型都是字符串类型,无法直接进行数值运算
- export加变量名可把变量提升为全局环境变量,可供其他 Shell 程序使用
3.3 特殊变量
3.3.1 $n
1 基本语法
$n (功能描述:n为数字,$0代表该脚本名称,$1-$9代表第一到第九个参数,十以上的参数,十以上的参数需要用大括号包含,如${10})
2 案例操作
[root@iZlu4gn37663k7Z datas]$ vim parameter.sh
#!/bin/bash
echo "$0 $1 $
[root@iZlu4gn37663k7Z datas]$ chmod 777 parameter.sh
[root@iZlu4gn37663k7Z datas]$ ./parameter.sh cls xz
./parameter.sh cls xz
3.3.2 $\
1 基本语法
$\#(功能描述:获取所有输入参数个数,常用于循环)。
2 案例实操
[root@iZlu4gn37663k7Z datas]$
#!/bin/bash
echo "$0 $1 $2"
echo $#
[root@iZlu4gn37663k7Z datas]$ chmod
parameter.sh cls xz
2
3.3.3 $*、$@
1 基本语法
$*(功能描述:这个变量代表命令行中所有的参数,$*把所有的参数看成一个整体)
$@(功能描述:这个变量也代表命令行中所有的参数,不过$@把每个参数区分对待)
注意:如果想让$*和$@ 体现区别必须用双引号括起来才生效,下文 for 循环中可以显示出区别
2 案例实操
[root@iZlu4gn37663k7Z datas]$ vim
#!/bin/bash
echo "$0 $1 $2"
echo $#
echo $*
echo $@
[root@iZlu4gn37663k7Z datas]$ bash parameter.sh 1 2 3
parameter.sh 1 2
3
1 2 3
1 2 3
3.3.4 $?
1 基本语法
$?(功能描述:最后一次执行的命令的返回状态。如果这个变量的值为 0,证明上一个命令正确执行;如果这个变量的值为非 0(具体是哪个数,由命令自己来决定),则证明上一个命令执行不正确了。0->True; !0->False)
2 案例实操
[root@iZlu4gn37663k7Z datas]$ ./helloworld.sh
hello world
[root@iZlu4gn37663k7Z datas]$ echo $?
0
4 运算符
1 基本语法
“$((运算式))”或“$[运算式]”
算术运算符 | 说明/含义 | ||
---|---|---|---|
+、- | 加法(或正号)、减法(或负号) | ||
*、/、% | 乘法、除法、取余(取模) | ||
** | 幂运算 | ||
++、-- | 自增和自减,可以放在变量的前面也可以放在变量的后面 | ||
!、&&、\ | \ | 逻辑非(取反)、逻辑与(and)、逻辑或(or) | |
<、<=、>、>= | 比较符号(小于、小于等于、大于、大于等于) | ||
==、!=、= | 比较符号(相等、不相等;对于字符串,= 也可以表示相当于) | ||
<<、>> | 向左移位、向右移位 | ||
~、\ | 、 &、^ | 按位取反、按位或、按位与、按位异或 | |
=、+=、-=、*=、/=、%= | 赋值运算符,例如 a+=1 相当于 a=a+1,a-=1 相当于 a=a-1 |
2 案例实操
计算(2+3)X4 的值
[root@iZlu4gn37663k7Z datas]# S=$[(2+3)*4]
[root@iZlu4gn37663k7Z datas]# echo $S
5 条件判断
1 基本语法
- test confition
[condition](注意condition前后要有空格)
注意:条件非空即为true,[aaa]返回true,[]返回false。
2 常用判断条件
字符串比较
- $str1 = $str2 : 相等比较
- $str1 != $str2 : 不等比较
- $str1 \\< $str2 : str1小于str2为true,比较字母在字母表顺序,字母越靠后就越大,反之越小
- $str1 \\> $str2 : str1大于str2为true,比较字母在字母表顺序,字母越靠后就越大,反之越小
- -n $str1 : str1长度不是0则为true
- -z $str1 : str1长度为0则为true,-z 是Zero简写
注:字符串比较大小,首先会将首个字符转化成ASCII码进行比较大小,如果相同会继续比较第二个字符以此类推,但是需要注意如果是数字类型的字符串如"12",进行比较会出问题,比较数字大小还是使用-gt、-lt等,大小号慎用。
在shell中 > 或 < 是输入或输出重定向符号,需要加反斜杠作转义
两个字符串比较时,比较符两边要有空格
两个整数之间比较
- -lt 小于(less than)
- -le 小于等于(less equal)
- -eq 等于(equal)
- -gt 大于(greater than)
- -ge 大于等于(greater equal)
- -ne 不等于(Not equal)
或且非
- -o : 或。用法:[ $value == "stop" -o $value == "restart" ]
- -a : 且。用法:[ $value == "stop" -a $value == "restart" ]
- || : 或。用法:[ $value == "stop" ] || [ $value == "restart" ]
- &&:且。用法:[ $value == "stop" ] && [ $value == "restart" ]
- ! : 非。用法:[ $value != "stop" ]
按照文件权限进行判断
- -r 有读的权限(read)
- -w 有写的权限(wr
- -x 有执行的权限(execute)
按照文件类型进行判断
- -f 文件存在并且是一个常规的文件(file)
- -e 文件存在(existence)
- -d 文件存在并是一个目录(directory)
3 案例实操
# 23 是否大于等于 22
[root@iZlu4gn37663k7Z datas]$ test 23 -ge 22
[root@iZlu4gn37663k7Z datas]$ echo $?
0
[root@iZlu4gn37663k7Z datas]$ [ 23 -ge 22 ]
[root@iZlu4gn37663k7Z datas]$ echo $?
0
# helloworld.sh 是否具有写权限
[root@iZlu4gn37663k7Z datas]$ test -w helloworld.sh
[root@iZlu4gn37663k7Z datas]$ echo $?
0
[root@iZlu4gn37663k7Z datas]$ [ -w helloworld.sh ]
[root@iZlu4gn37663k7Z datas]$ echo $?
0
# /home/atguigu/cls.txt 目录中的文件是否存在
[root@iZlu4gn37663k7Z datas]$ test -e /home/atguigu/cls.txt
[root@iZlu4gn37663k7Z datas]$ echo $?
1
[root@iZlu4gn37663k7Z datas]$ [ -e /home/atguigu/cls.txt ]
[root@iZlu4gn37663k7Z datas]$ echo $?
1
# 多条件判断(&& 表示前一条命令执行成功时,才执行后一条命令,|| 表示上一条命令执行失败后,才执行下一条命令)
[root@iZlu4gn37663k7Z ~]$ [ condition ] && echo OK || echo notok
OK
[root@iZlu4gn37663k7Z datas]$ [ condition ] && [ ] || echo notok
notok
6 流程控制
6.1 if 判断
1 基本语法
# 无分支if
if [ 条件判断式 ]
then
程序块
fi # 结束,类似于end
# 多分支的if
if [ 条件判断式 ]
then
程序块
elif [ 条件判断式 ]
then
程序块
else
程序块
fi
2 注意事项
- [ 条件判断式 ],中括号和条件判断式之间必须有空格
- if 后要有空格
3 案例实操
# !/bin/bash
if [ $1 -eq "1" ]
then
echo "输入的是1"
elif [ $1 -eq "2" ]
then
echo "输入的是2"
else
echo "超出理解范围"
fi
6.2 case 语句
1 基本语法
case $变量名 in
"值1")
若变量值等于值1,则执行该程序块
;;
"值2")
若变量值等于值2,则执行该程序块
;;
*)
若变量值都不是以上值,则执行该程序块
;;
esac # 结束,类似于end
2 注意事项:
- case 行尾必须为单词 “in” ,每一个模式匹配必须以右括号 “)” 结束
- 双分号 “;;” 表示命令序列结束,相当于break
- 最后的 “*)” 表示默认模式,相当于default
3 案例实操
# !/bin/bash
case $1 in
"1")
echo "输入的是一"
;;
"2")
echo "输入的是二"
;;
*)
echo "超出理解范围"
;;
esac
6.3 for 循环
1 基本语法1
for (( 初始值;循环控制条件;变量变化 ))
do
程序
done
2 案例实操
# !/bin/bash
# 从1加到100
s=0 # 不能有空格(不能写成s = 0)
for (( i=0; i<=100; i++ ))
do
s=$[$s+$i]
done
echo $s
1 基本语法2
for 变量 in 值1 值2 值3...
do
程序
done
2 案例实操
# !/bin/bash
# 打印所有参数"$*"
for i in $*
do
echo "这是参数$i"
done
[root@iZlu4gn37663k7Z shell_learn]# sh for2.sh as fds gdf hg dsf
这是参数as
这是参数fds
这是参数gdf
这是参数hg
这是参数dsf
# !/bin/bash
# 查看 $* 和 $@ 的区别
echo "=======================带双引号==========================="
echo '$*:'
for i in "$*"
#$*中的所有参数看成是一个整体,所以这个 for 循环只会循环一次
do
echo "$i"
done
echo '$@:'
for j in "$@"
#$@中的每个参数都看成是独立的,所以“$@”中有几个参数,就会循环几次
do
echo "$j"
done
echo "======================不带双引号=========================="
echo '$*:'
for i in $*
do
echo "$i"
done
echo '$@:'
for j in $@
do
echo "$j"
done
[root@iZlu4gn37663k7Z shell_learn]# sh for3.sh a b c d e
=======================带双引号===========================
$*:
a b c d e
$@:
a
b
c
d
e
======================不带双引号==========================
$*:
a
b
c
d
e
$@:
a
b
c
d
e
此时可回顾本文3.3.3。
6.4 while 循环
1 基本语法
while [ 条件判断式 ]
do
程序
done
2 案例实操
# !/bin/bash
# 从1加到100
s=0
i=1
while [ $i -le 100 ]
do
s=$[$s+$i]
i=$[$i+1]
done
echo $s
7 read 读取控制台输入
1 基本语法
read(选项)(参数)
# 选项:
# -p:指定读取值时的提示符
# -t:指定读取值时等待的时间
# 参数:
# 变量:指定读取值时的变量名
2 案例实操
# !/bin/bash
# 10s内输入(-t的作用),并且提示输入y/n(-p的作用),将用户输入内容赋给 INPUT 这个变量
read -t 10 -p "Whether to install this software <y/n>?" INPUT
while [ $INPUT != 'y' ] && [ $INPUT != 'n' ]
do
read -t 10 -p ".............................>" INPUT
done
if [ $INPUT == 'y' ]
then
echo "Installing, please wait..."
elif [ $INPUT == 'n' ]
then
echo "Bye"
fi
[root@iZlu4gn37663k7Z shell_learn]# sh read.sh
Whether to install this software <y/n>?y
Installing, please wait...
[root@iZlu4gn37663k7Z shell_learn]# sh read.sh
Whether to install this software <y/n>?n
Bye
[root@iZlu4gn37663k7Z shell_learn]# sh read.sh
Whether to install this software <y/n>?dsf
.............................>fhf
.............................>c
.............................>dtr
.............................>bfd
.............................>n
Bye
[root@iZlu4gn37663k7Z shell_learn]# sh read.sh
Whether to install this software <y/n>?sdf
.............................>fh
.............................>y
Installing, please wait...
8 函数
8.1 系统函数
8.1.1 basename
1 基本语法
basename [string / pathname] [suffix]
(功能描述:basename 命令会删掉所有的前缀包括最后一个(‘/’)字符,然后将字符串显示出来。
2 参数解释
string / pathname:一段字符串或某个路径。
suffix 为后缀,如果 suffix 被指定了,basename 会将 pathname 或 string 中的 suffix 去掉。
3 案例实操
# 截取该/home/admin/test.txt 路径的文件名称
[atguigu@hadoop101 datas]$ basename /home/admin/test.txt
test.txt
[atguigu@hadoop101 datas]$ basename /home/admin/test.txt .txt
test
8.1.2 dirname
1 基本语法
dirname 文件绝对路径
(功能描述:从给定的包含绝对路径的文件名中去除文件名(非目录的部分),然后返回剩下的路径(目录的部分))
2 案例实操
# 获取 test.txt 文件的路径
[atguigu@hadoop101 ~]$ dirname /home/admin/banzhang.txt
/home/admin
8.2 自定义函数
1 基本语法
# 定义函数
[ function ] funname[()]
{
Action;
[return int;]
}
# 调用函数
funname
2 经验技巧
- 必须在调用函数地方之前,先声明函数,shell 脚本是逐行运行。不会像其它语言一 样先编译。
- 函数返回值,只能通过$?系统变量获得,可以显示加:return 返回,如果不加,将以最后一条命令运行结果,作为返回值。return 后跟数值 n(0-255),只能return 0-255 之间的整数
3 案例实操
# !/bin/bash
# 两数之和
function sum()
{
s=0
s=$[$1+$2]
echo "$s"
}
read -p "Please input the number1: " n1;
read -p "Please input the number2: " n2;
sum $n1 $n2;
[root@iZlu4gn37663k7Z shell_learn]# sh sum.sh
Please input the number1: 1
Please input the number2: 2
3
9 Shell 工具
9.1 cut
cut 的工作就是“剪”,具体的说就是在文件中负责剪切数据用的。cut 命令从文件的每一行剪切字节、字符和字段并将这些字节、字符和字段输出。
1 基本用法
cut [ 选项参数 ] filename
说明:默认分隔符是制表符
2 选项参数说明
选项参数 | 功能 |
---|---|
-f | 列号,提取第几列 |
-d | 分隔符,按照指定分隔符分割列 |
-c | 指定具体的字符 |
3 案例实操
[root@iZlu4gn37663k7Z shell_learn]# vim cut.txt
wo ta
jiao shi
ba an
nie na
bo ka
he lie
fu ni
o na
[root@iZlu4gn37663k7Z shell_learn]# cut -d ' ' -f 1 cut.txt
wo
jiao
ba
nie
bo
he
fu
o
[root@iZlu4gn37663k7Z shell_learn]# cut -d ' ' -f 1,2 cut.txt
wo ta
jiao shi
ba an
nie na
bo ka
he lie
fu ni
o na
[root@iZlu4gn37663k7Z shell_learn]# cut -d ' ' -f 1 cut.txt | grep nie | cut -d ' ' -f 1
nie
[root@iZlu4gn37663k7Z shell_learn]# cut -c 1 cut.txt
w
j
b
n
b
h
f
o
9.2 awk
一个强大的文本分析工具,把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行分析处理。
1 基本语法
awk [ 选项参数 ] ‘pattern1{action1} pattern2{action2}...’ filename
pattern:表示 AWK 在数据中查找的内容,就是匹配模式
action:在找到匹配内容时所执行的一系列命令
2 选项参数说明
选项参数 | 功能 |
---|---|
-F | 指定输入文件折分隔符 |
-v | 赋值一个用户定义变量 |
3 案例实操
9.3 sort
sort 命令是在 Linux 里非常有用,它将文件进行排序,并将排序结果标准输出。
1 基本语法
sort(选项)(参数)
选项 | 说明 |
---|---|
-n | 依照数值的大小排序 |
-r | 以相反的顺序来排序 |
-t | 设置排序时所用的分隔字符 |
-k | 指定需要排序的列 |
参数:指定待排序的文件列表
2 案例实操
# 数据准备
[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
# 按照“:”分割后的第三列倒序排序。
[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