Shell 学习笔记

Shell

学习目的:
1.看懂Shell程序
2.编写简单Shell程序管理集群、提高开发效率

Shell概述

外层应用程序通过Shell命令行解释器,调用操作系统的内核。
Shell易编写、易调试、灵活性强。

Shell解析器

Linux提供的Shell解析器有

[ranan@hadoop100 ~]$ sudo cat /etc/shells 
/bin/sh
/bin/bash
/usr/bin/sh
/usr/bin/bash

其中sh与bash的关系,sh调用仍然是bash。
sh(Bourne shell)的增强版bash(Bourne Again SHell)

image

CentOs默认的解析器是bash

[ranan@hadoop100 ~]$ echo $SHELL
/bin/bash

Shell脚本入门

脚本格式

脚本以#!/bin/bash开头 指定bash解析器

HelloWorld

需求:创建一个shell脚本,输出HelloWorld

1.创建HelloWorld.sh

[ranan@hadoop100 datas]$ touch HelloWorld.sh
[ranan@hadoop100 datas]$ vim HelloWorld.sh

2.编写HelloWorld.sh

#!/bin/bash
echo "HelloWorld"

3.执行HelloWorld.sh

方式一:本质是bash解析器帮你执行脚本,所以脚本本身不需要执行权限

[ranan@hadoop100 datas]$ sh HelloWorld.sh 
HelloWorld
[ranan@hadoop100 datas]$ bash HelloWorld.sh 
HelloWorld

方式二:本质是脚本自己需要执行,所以需要执行权限

image

多命令脚本

需求:脚本batch.sh 在/home/ranan/datas下创建banzhang.txt,banzhang.txt中增加'my name is ranan'
1.创建batch.sh

[ranan@hadoop100 datas]$ touch batch.sh
[ranan@hadoop100 datas]$ vim batch.sh 

2.编写batch.sh

#!/bin/bash
cd /home/ranan/datas
touch banzhang.txt
echo "my name is ranan" >> banzhang.txt

3.执行batch.sh

image

Shell中的变量

系统变量

常见的系统变量:$PWD $HOME $SHELL $USER 等

家目录
[ranan@hadoop100 datas]$ echo $HOME
/home/ranan

默认shell解析器
[ranan@hadoop100 datas]$ echo $SHELL
/bin/bash

当前用户
[ranan@hadoop100 datas]$ echo $USER
ranan

当前路径
[ranan@hadoop100 datas]$ echo $PWD
/home/ranan/datas

自定义变量

基本语法

定义变量:变量=值 等号两边不能留有空格
撤销变量:unset 变量
变量使用:echo $变量 取值才加$
声明静态变量: readonly 变量=值。不能unset

[ranan@hadoop100 datas]$ A=1
[ranan@hadoop100 datas]$ echo $A
1
[ranan@hadoop100 datas]$ unset A

变量定义规则

1、变量名称可以由字母,数字和下划线组成,不能以数字开头,环境变量名建议大写
2.等号两侧不能有空格
3.在bash中,变量默认类型都是字符串类型,无法直接进行数值运算

[ranan@hadoop100 datas]$ C=1+1
[ranan@hadoop100 datas]$ echo $C
1+1

4.变量的值如果有空格,需要使用双引号或单引号括起来

[ranan@hadoop100 datas]$ D="my name"
[ranan@hadoop100 datas]$ echo $D
my name

5.可把变量提升为全局变量,可供其他shell程序使用
语法:export 变量

image

[ranan@hadoop100 datas]$ export A

image

特殊变量$n

功能描述
n为数字 $0代表该脚本名称,$1-$9代表第一个到第九个参数,第十个以上的参数需要用大括号括住${10}

案例
输出脚本名,第一个参数和第二个参数

[ranan@hadoop100 datas]$ touch parameter.sh
[ranan@hadoop100 datas]$ vim parameter.sh 
[ranan@hadoop100 datas]$ cat parameter.sh 
#!/bin/bash
echo "$0 $1 $2"
[ranan@hadoop100 datas]$ bash parameter.sh 
parameter.sh
[ranan@hadoop100 datas]$ bash parameter.sh myname ranan
parameter.sh myname ranan
[ranan@hadoop100 datas]$ 

$# 输入参数的个数

功能描述
获取所有输入参数个数,常用于循环

案例

[ranan@hadoop100 datas]$ vim parameter.sh 
[ranan@hadoop100 datas]$ cat parameter.sh 
#!/bin/bash
echo $#
[ranan@hadoop100 datas]$ bash parameter.sh  myname is ranan
3

$* 和 $@ 所有的参数

  • $* 代表命令行中所有的参数,把所有参数看成一个整体
  • $@ 也代表命令行中所有的参数,不过把每个参数区分对待
[ranan@hadoop100 datas]$ vim parameter.sh 
[ranan@hadoop100 datas]$ cat parameter.sh 
#!/bin/bash
echo $*
echo $@
[ranan@hadoop100 datas]$ bash parameter.sh  my name is ranan
my name is ranan
my name is ranan

$? 最后一次执行命令的状态

最后一次执行命令的状态
0:上一条命令正确执行
非0:上一条命令执行不正确

[ranan@hadoop100 datas]$ bash HelloWorld.sh 
HelloWorld
[ranan@hadoop100 datas]$ echo $?
0
[ranan@hadoop100 datas]$ echo$?
bash: echo0: 未找到命令...
相似命令是: 'echo'
[ranan@hadoop100 datas]$ echo $?
127

运算符

$((运算式)) 或 $[运算式]
expr +,-,*,/,% 加减乘除取余
expr运算符间要有空格

$[运算式]常用

案例

1.计算3+2

[ranan@hadoop100 datas]$ expr 2+3
2+3
[ranan@hadoop100 datas]$ expr 2 +3
expr: syntax error: unexpected argument “+3”

[ranan@hadoop100 datas]$ expr 2 + 3
5

2.计算(2+3)*4

方式1``代表括号

[ranan@hadoop100 datas]$ expr `expr 2 + 3` \* 4
20

方式2

[ranan@hadoop100 datas]$ echo $[(2+3)*4]
20

条件判断

基本语法

[ condition ]
注意
1.condition前后要有空格
2.条件非空返回true

常用判断条件

两个整数之间比较

= 字符串比较

符号 描述
-lt (less than)小于
-le (less equal) 小于等于
-eq (equal)等于
-gt (greater than) 大于
-ge (greater equal) 大于等于
-ne (not equal) 不等于

按照文件权限比较

-r 有读的权限
-w 有写的权限
-x 有执行的权限(execute)

文件类型判断

-f 文件存在并且是一个常规文件(file)
-e 文件存在(existence)
-d 文件存在并是一个目录(directory)

多条件判断

$$ 逻辑与
|| 逻辑或

案例

判断23是否大于2

[ranan@hadoop100 datas]$ [ 23 -gt 2 ]
[ranan@hadoop100 datas]$ echo $?
0

判断helloworld.sh是否有写入权限

[ranan@hadoop100 datas]$ [ -w hellowrld.sh ]
[ranan@hadoop100 datas]$ echo $?
1

判断目录中文件是否存在

[ranan@hadoop100 datas]$ [ -e /home/ranan/datas ]
[ranan@hadoop100 datas]$ echo $?
0

流程控制

if条件判断

基本语法

写法1
if [空格 条件判断式 空格];then
程序
fi

写法2
if[空格 条件判断式 空格]
then
程序
fi

案例

[ranan@hadoop100 datas]$ cat if.sh
#!/bin/bash
if [ $1 -eq 1 ]
then
	echo "班长真帅"
elif [ $1 -eq 2 ]
then
	echo "班长真丑"
fi
[ranan@hadoop100 datas]$ bash if.sh 2
班长真丑

case语句

基本语法

case 变量名 in
"值1")
如果变量值等于值1执行程序1
;;
"值2")
如果变量值等于值2执行程序2
;;
*)
如果都不是,执行这里的代码块
;;
esac

案例

[ranan@hadoop100 datas]$ cat case.sh

#!/bin/bash
case $1 in
1)
	echo "班长"
;;
2)
	echo "学习委员"
;;
3)
	echo "体育委员"
;;
esac
[ranan@hadoop100 datas]$ bash case.sh 2
学习委员

for循环

基本语法

写法1

for((初始值;循环控制条件;变量变化))
do
程序
done

写法2

for 变量 in 值1 值2 值3
do
程序
done

案例

写法1

[ranan@hadoop100 datas]$ cat for.sh
#!/bin/bash
s=0
for((i=1;i<=100;i++))
do
	s=$[$s+$i]	
done
echo $s
[ranan@hadoop100 datas]$ bash for.sh
5050

写法2

[ranan@hadoop100 datas]$ cat for2.sh
#!/bin/bash
for i in $*
do
	echo $i
done
[ranan@hadoop100 datas]$ bash for2.sh 1 2
1
2

区分$*与$@

加了引号,$*会被看成一个整体

[ranan@hadoop100 datas]$ cat for2.sh
#!/bin/bash
for i in "$*"
do
	echo $i
done
for i in "$@"
do
	echo $i
done
[ranan@hadoop100 datas]$ bash for2.sh 1 2
1 2
1
2

while循环

基本语法

while [ 条件判断式 ]
do
程序
done

案例

[ranan@hadoop100 datas]$ cat while.sh
#!/bin/bash
s=0
i=1
while [ $i -le 100 ]
do
	s=$[$s + $i]
	i=$[$i + 1]
done
echo $s

[ranan@hadoop100 datas]$ bash while.sh
5050

read读取控制台输入

基本语法
read 常用选项 参数

常用选项

-p 指定读取值时的提示符
-t 指定读取值时等待的时间(秒)

参数

变量:指定读取值的变量名

案例
提示7秒内,读取控制台输入的名称

[ranan@hadoop100 datas]$ cat red.sh
#!/bin/bash
read -t 7 -p "在7s内请输入你的名字" NAME
echo $NAME
[ranan@hadoop100 datas]$ bash red.sh
在7s内请输入你的名字ranan
ranan

函数

系统函数

basename

基本语法
basename [string / path] [suffix]

说明
basename命令会删掉所有的路径前缀包括最后一个‘/’字符,然后将文件名称以字符串形式展现出来
suffix表示后缀,如果suffix被指定了,basename会删除string/path中的后缀。

获取文件的名称

案例

[ranan@hadoop100 datas] basename /home/linux/banzhang.txt
banzhang.txt

[ranan@hadoop100 datas]$ basename /home/linux/banzhang.txt .txt
banzhang

dirname

基本语法
dirname 文件的绝对路径

描述

从给定的包含绝对路径的文件名中去除文件名(非目录的部分),然后返回剩下的路径(目录的部分)

获取文件所在的路径(不包含文件本身)

案例

[ranan@hadoop100 datas]$ dirname /home/linux/banzhang.txt
/home/linux

自定义函数

基本语法

[ function ] 函数名[()]
{
Action:
[return int;] 一般不采用
}
funname

说明
1.必须在调用函数之前声明函数,shell逐行执行,不会先编译。
2.函数返回值只能通过$?获取,将以最后一条命令的运行结果,作为返回值。可以显示添加return 数值(0-255),和以前的返回值意思不一样,返回的是运行结果状态。

案例

1.计算输入两个参数的值

[ranan@hadoop100 datas]$ cat sum.sh
#!/bin/bash
function sum(){
	s=0;
	s=$[$1 + $2]
	echo $s
}
read -p "input your param1:" P1
read -p "input your param2:" P2
sum $P1 $P2
[ranan@hadoop100 datas]$ bash sum.sh
input your param1:1
input your param2:2
3

Shell工具

cut剪切

基本语法
cut [选项参数] filename

说明
cut命令从文件的每一行剪切字节,字符和字段并将这些字节,字符和字段输出

选项参数
-f 列号,提取第几列
-d 分隔符,原文件按照指定分隔符分隔列

案例
切割cut.txt第一列
切割cut.txt第二列和第三列

[ranan@hadoop100 datas]$ cat cut.txt
dong shen
guan zhen
wo wo
lai  lai 两个空格
le  le  两个空格
[ranan@hadoop100 datas]$ cut -d " " -f 1 cut.txt 
dong
guan
wo
lai
le
[ranan@hadoop100 datas]$ cut -d " " -f 2,3 cut.txt 
shen
zhen
wo
 lai
 le

2.获取guan

[ranan@hadoop100 datas]$ cat cut.txt | grep guan
guan zhen
[ranan@hadoop100 datas]$ cat cut.txt | grep guan | cut -d " " -f 1
guan

3.PATH变量第二个:开始后的所有路径
3- 表示第三列及以后

[ranan@hadoop100 datas]$ echo $PATH | cut -d ":" -f 3-
/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin

sed流编辑器

基本语法
sed [选项参数] ‘命令’ filename

说明
sed是一种流编辑器,它一次处理一行内容,处理时,把当前处理的行存储在临时缓冲区中,成为“模式空间”,接着sed命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕,接着处理下一行,这样不断重复,知道文件末尾,文件内容并没有改变。除非你使用重定向存储输出

常用选项

-e 适用于多条指令,每条指令前面加-e

命令说明

行号a 内容 新增
行号d/ 或者 /内容/d 删除
s 查找并替换

案例

1.在空格行(5行)后增加shang hai字符

[ranan@hadoop100 datas]$ cat cut.txt 
dong shen
guan zhen
wo wo
lai  lai

le  le
[ranan@hadoop100 datas]$ sed "5a shang hai" cut.txt
dong shen
guan zhen
wo wo
lai  lai

shang hai
le  le

2.每一行的后新增一行,新增行内容哦为!

[ranan@hadoop100 datas]$ sed "a !" cut.txt 
dong shen
!
guan zhen
!
wo wo
!
lai  lai
!

!
le  le
!

3.删除wo这一行

# 方式1
[ranan@hadoop100 datas]$ sed "3d" cut.txt 
dong shen
guan zhen
lai  lai

le  le

# 方式二
[ranan@hadoop100 datas]$ sed "/wo/d" cut.txt 
dong shen
guan zhen
lai  lai

le  le
[ranan@ha

4.将wo替换成ni g全局替换,不加只替换一个

# 替换一个
[ranan@hadoop100 datas]$ sed "s/wo/ni/" cut.txt 
dong shen
guan zhen
ni wo
lai  lai

le  le

# 全局替换
[ranan@hadoop100 datas]$ sed "s/wo/ni/g" cut.txt 
dong shen
guan zhen
ni ni
lai  lai

le  le

5.删除第二行并将wo换成ni
两条指令了,需要使用-e

[ranan@hadoop100 datas]$ sed -e  "2d" -e "s/wo/ni/g" cut.txt 
dong shen
ni ni
lai  lai

le  le

awk

语法
awk [选项参数] 'pattern1 {action1} pattern2{action2}..' filename

pattern:表示awk在数据中查找的内容,就是匹配模式
action:在找到匹配内容时执行的一系列命令

说明
awk 一个强大文件分析工具,把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行分析处理

常用选项

-F 指定输入文件分隔符
-v 赋值一个用户定义变量

内置变量
FILENAME 文件名
NR 已读的记录数,当前行数
NF 切割后,列的个数
$NF 最后一个域,最后一列

案例

数据文件

image

1.搜索passwd文件以root关键字开头的所有行,并输出该行的第1,7列,以逗号输出
第一列可以用$1或$0表示

[ranan@hadoop100 datas]$ awk -F : '/^root/{print $1","$7}' passwd

2.显示第1,7列,以逗号分割,且在开头添加列名user,最后一行添加"ranan,"

[ranan@hadoop100 datas]$ awk -F : 'BEGIN{print "user,"} /^root/{print $1","$7} END{print "ranan,"}' passwd

3.用户id(第三列)增加数值1并输出
这里变量的使用不用加$

[ranan@hadoop100 datas]$ awk -F : -v i=1 '{print $3+i}' passwd
[ranan@hadoop100 datas]$ awk -F : '{print $3+1}' passwd

4.统计passwd文件名,每行的行号,每行的列数

awk -F '{print FILENAME "," NR "," NF}' passwd

5.查询sed.txt中空行所在的行号

awk -F '/^$/{print NR}' sed.txt中

sort排序

基本语法

sort [选项] [参数]

说明
sort 命令是在Linux里非常有用,它将文件进行排序,并将排序结果标准输出

常见选项

参数 描述
-n 依照数值大小排序
-r 以相反的顺序排序
-t 设置排序时使用的分隔字符
-k 指定需要排序的列

案例

以打到小的顺序排序第二列

[ranan@hadoop100 datas]$ cat sort 
bb:40:5.4
cc:50:6.6
dd:10:1.6
ee:20:2
[ranan@hadoop100 datas]$ sort -t : -nrk 2 sort
cc:50:6.6
bb:40:5.4
ee:20:2
dd:10:1.6

面试题

问题1:使用Linux命令查询file中空行所在的行号

空行:/^$/

awk '/^$/{print NR}' file

问题2:有文件chengji.txt如下
张三 40
李四 50
王五 60
用Linux命令计算第二列的和并输出

cat chengji.txt | awk -F " " '{sum+=$2} END{print sum}'

问题3:Shell脚本里如何检查一个文件是否存在,如果不存在该如何处理

#!/bin/bash
if [ -f file.txt ]
then
	echo "文件存在"
elif
	echo"文件不存在"
fi

问题4:用shell写一个脚本,对test.txt文本中无序的一列数字排序

9
8
7
6
4
5
10
2

sort -n test.txt

问题5:请用shell脚本查找当前文件夹(/home)下所有文本内容中包含'shen'的文件名称

[ranan@hadoop100 datas]$ grep -r "shen" /home
/home/ranan/datas/o d:dong shen
/home/ranan/datas/abc:shen

写法1

[ranan@hadoop100 datas]$ grep -r "shen" /home | cut -d : -f 1
/home/ranan/datas/o d
/home/ranan/datas/abc

写法2

[ranan@hadoop100 datas]$ grep -r "shen" /home | awk -F : '{print $1}'
/home/ranan/datas/o d
/home/ranan/datas/abc
posted @ 2021-07-28 20:30  rananie  阅读(198)  评论(0编辑  收藏  举报