Shell编程(shell概述、变量操作、流程控制、函数、shell工具)

一、Shell概述

在这里插入图片描述
Linux系统的核心是内核。内核控制着计算机系统上的所有硬件和软件,在必要时为应用程序分配硬件, 并根据需要执行程序中的代码。
内核主要负责以下四种功能:

  • 系统内存管理
  • 软件程序管理
  • 硬件设备管理
  • 文件系统管理
    简单来说Shell是一种特殊的交互式工具,核心是命令提示符,允许输入文本命令,解释命令,并在内核中执行命令。

1.shell的由来

  • Linux操作系统的核心是kernal(内核)!
    当应用程序在执行时,需要调用计算机硬件的cpu,内存等资源。
  • 程序将指令发送给内核执行。
  • 为了防止程序发送一些恶意指令导致损坏内核,在内核和应用程序接口之间,设置一个中间层,称为shell!
  • 用户编写的程序,经过shell解释给内核,内核执行的结果再由shell返回给程序。shell所支持的命令都是对内核没有威胁,没有损害的。

2.shell是什么

本质上来说:
shell: 一个可以解释shell规定的语法命令的解释器。 解释器负责将应用程序发送的指令,进行检查,合法后交给内核解释执行!返回结果!
shell命令: shell解释器要求的指定语法编写的命令。
shell脚本: 多条shell命令,可以编写在一个文件中,文件中的指令,可以按照顺序执行。将这个文件称为shell脚本!

3.shell中的解释器

使用$SHELL 变量查看当前系统默认的解释器类型
在这里插入图片描述

shell支持多种不同风格的解释器,通过/etc/shells文件查看
在这里插入图片描述
Centos默认的解析器是bash

在终端中输入: cat /etc/shells , 等价于/bin/bash -c ‘cat /etc/shells’。 默认/bin/bash必须接一个脚本,作为输入!如果是一条命令,需要加-c (command)

4.linux的环境变量

使用echo $PATH查看linux系统中的环境变量。 在这里插入图片描述
本质上来说,我们所执行的命令都是一些文件。如pwd,cd,echo等,它们都在/bin目录下。
之所以它们可以在任何目录下能以 文件名 参数的形式运行,是应为它们的根目录在环境变量中。
如,我们自己编写一个shell文件,保存在/home/shell目录下
在这里插入图片描述
文件内容为
在这里插入图片描述
我们在使用source命令的方式运行该脚本文件,发现跳转到了/usr/local目录并显示了该目录下文件内容
在这里插入图片描述
但是如果在其他目录中直接以文件名运行,会显示未找到命令。这是应为该
在这里插入图片描述
除此之外,还可以用./文件名方式执行该文件。
先给该脚本文件赋上权限,再执行该文件
在这里插入图片描述
发现该脚本文件执行成功。
但我们离开该目录,用 文件名的方式执行该文件
在这里插入图片描述
发现找不到该命令
我们将该文件复制到某个环境遍历目录下,如/bin目录。
在这里插入图片描述
运行该文件,则发现执行成功!

5.第一个shell文件

在/home/shell目录下创建一个文件test01.sh
编辑该文件,内容如下
在这里插入图片描述
保存并退出
执行该文件的三种方式

  1. bash或者sh + 脚本
    在这里插入图片描述
    特点: 新开一个bash执行脚本,一旦脚本执行完毕,bash自动关闭!
  2. ./脚本文件,前提是当前用户对脚本有执行权限,使用当前默认的解释器执行脚本
    在这里插入图片描述
    特点: 新开一个bash执行脚本,一旦脚本执行完毕,bash自动关闭
  3. source +脚本 或者 . +脚本 。应为.就是source的缩写
    在这里插入图片描述

6.脚本的编写要求

  1. 声明: #!/bin/bash
  2. 正文: 必须是shell解释器能否解释的命令

7.脚本的执行

  • bash 或 sh + 脚本 。
    特点: 新开一个bash执行脚本,一旦脚本执行完毕,bash自动关闭
  • ./脚本,前提是当前用户对脚本有执行权限,使用当前默认的解释器执行脚本
    特点: 新开一个bash执行脚本,一旦脚本执行完毕,bash自动关闭!
  • source 或 . +脚本 使用当前默认的解释器执行脚本,并不要求当前用户对脚本有执行权限
    特点: 在当前bash执行脚本

二、变量操作

1.变量的增删改查

增: 变量名=变量值	(注意:=号的左边和右边不能有空格且区分大小写)
删:unset 变量名
改:变量名=变量值	(注意:=号的左边和右边不能有空格且区分大小写)
查:echo $变量名		set 查看当前定义的所有的变量

定义一个变量a=1,查看该变量
在这里插入图片描述
把变量a的值修改为2并打印
在这里插入图片描述
查看所有的变量 set

在这里插入图片描述
删除变量a的值

在这里插入图片描述

2.特殊关键字

  • readonly : 用来修饰一个只读(不能修改,删除)变量!
  • export: 导出!将一个变量提升为全局变量!
  • 局部变量: 默认变量只在定义变量的bash中有效!
    如果希望在bash-a访问bash-b中定义的变量!
    要求:①bash-b不能关闭
    ②让bash-b将变量提升为全局变量,才能访问到!
    在这里插入图片描述

3.变量的生命周期

变量的生命周期:

  • 在第一次新增时产生
  • 变量在执行unset时,撤销,失效!
  • 关闭当前bash,所有定义的变量也不会存在!

在这里插入图片描述
重新连接后,该变量消失
在这里插入图片描述
注意:

  1. 变量赋值时,值全部以字符串存在,无法进行运算
  2. 赋值的值中有空格,需要使用引号引起来。单引号:不能识别$等特殊字符。双引号:可以使用 $字符
``的作用是将引号中的命令执行的结果赋值给变量  
 `命令` 等价于 $(命令)

4.特殊变量

  1. $? :上一条命令的返回值。在bash中,若返回值为0,代表上一条命令执行成功。
  2. $# :参数个数
  3. $* :参数列表
  4. $@ :参数列表
  5. $0脚本名
  6. $1~n :第n个参数。获取第10个以上的参数时要使用 ${n}

5.运算符

[1]基本语法
(1)“$((运算式))” 或 “$[运算式](2) expr  + , - , \*,  /,  %    加,减,乘,除,取余

注意:expr运算符间要有空格;
*号需要转义为 \*,否则会被视为通配符;
运算指的都是整数的运算,浮点运算需要借助其他的命令!

[2]案例
  1. 计算3+2的值
[atguigu@hadoop101 datas]# expr 2 + 3
5
  1. 计算3-2的值
[atguigu@hadoop101 datas]# expr 3 - 2 
1
  1. 计算(2+3)X4的值
expr一步完成计算
[atguigu@hadoop101 datas]# expr `expr 2 + 3` \* 4
20
采用$[运算式]方式
[atguigu@hadoop101 datas]# S=$[(2+3)*4]
[atguigu@hadoop101 datas]# echo $S

6.条件判断

[1]基本语法

[ condition ](注意condition前后要有空格
注意:条件非空即为true,[ atguigu ]返回true ,[] 返回false。在linux中true为0,false为1

[2]常用判断条件
  1. 两个整数之间比较
    = 字符串的比较,判断两个字符串是否相等. = 两侧要有空格
    -lt 小于(less than) -le 小于等于(less equal)
    -eq 等于(equal) -gt 大于(greater than)
    -ge 大于等于(greater equal) -ne 不等于(Not equal)
例:23是否大于等于22
 [ 23 -ge 22 ]
 echo $?
 返回结果为0 即true
  1. 按照文件权限进行判断
    -r 有读的权限(read) -w 有写的权限(write)
    -x 有执行的权限(execute)
例:判断test01.sh是否具有写权限
[ -w test01.sh ]
 echo $?
 返回结果为0 即true
  1. 按照文件类型进行判断
    -f 文件存在并且是一个常规的文件(file)
    -e 文件存在(existence) -d 文件存在并是一个目录(directory)
    -s 文件存在且不为空 -L 文件存在且是一个链接(link)
例:判断test01.sh是否是常规文件
[ -f test01.sh ]
echo $?
返回结果为0,即为true

多条件判断(&& 表示前一条命令执行成功时,才执行后一条命令,|| 表示上一条命令执行失败后,才执行下一条命令)

三、流程控制

1. if判断

if [ 条件判断式 ] 
  then 
程序 
elif 条件判断式
	then 程序..
else 程序..
fi

注意:then必须另起一格。如果非要和if [条件判断式]写在一行,则需要在then的左侧加上 ;
例:写一个简单的bash文件,要求:若用户输入的是1,则输出用户输出的是1;用户输入的是2,则输出用户输入的是2;若用户输入的是3,则输出用户输出的是3,若用户输入的是其他字符,则输出用户输入的不是1,2 ,3

# ! bin/bish
#若用户输入的是1,则输出用户输出的是1;用户输入的是2,则输出用户输入的是2;若用户输入的是3,则输出用户输出的是3
if [ $1 -eq 1 ]
then
    echo 用户输入的是1
elif [ $1 -eq 2  ]
then
    echo 用户输入的是2
elif [ $1 -eq 3  ]
then
    echo 用户输入的是3
else
    echo 用户输入的不是1,2,3
fi

测试
在这里插入图片描述
注意:

  • 若使用linux风格的条件判断语句,if、then、等和 [ 条件判断 ]之间必须要有空格。且then要另起一行或者在then的左侧加上 ;
  • 若使用C语言风格的条件判断,则无需考虑这些。但C语言风格的判断需要写两个括号,如判断第一个参数是否等于1,if(($1==1))

2.case 语句

基本语法

case $变量名 in 
  "值1")
  如果变量的值等于值1,则执行程序1 ;; 
  "值2") 
    如果变量的值等于值2,则执行程序2 ;; 
  …省略其他分支… 
  *) 
    如果变量的值都不是以上的值,则执行此程序 ;; 
esac

注意事项:

  • case行尾必须为单词“in”,每一个模式匹配必须以右括号“)”结束。
  • 双分号“;;”表示命令序列结束,相当于java中的break。最后的“*)”表示默认模式,相当于java中的default

例:输入一个字符串,如果是guest,则输出欢迎游客,如果是admin,则输出欢迎管理员,如果是其它,输出不欢迎

#! /bin/bash/
#判断用户谁让的参数,若为guest,则输出欢迎游客登录,如果是admin,则输出欢迎管理员,如果是其他,则输出不欢迎
case $1 in
guest)
        echo 欢迎游客登录 ;;
admin)
        echo 欢迎管理员 ;;
*)
        echo 不欢迎 ;;
esac

测试结果
在这里插入图片描述

3.for循环

基本语法

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

例:计算1到100之间的和

#!/bin/bash
#计算1到100之间的和
sum=0
for((i=1;i<=100;i++))
do
  sum=$[$sum+$i]
done
echo 1~100之间的和为: $sum

测试结果
在这里插入图片描述

4.增强for循环

基本语法

for 变量 in 值1 值2 值3… 
  do 
    程序 
  donefor 变量 in 1 2 3; do 程序; donefor 变量 in {1..3}; do 程序; done

例1:遍历集合中每个元素的值

#!/bin/bash
#遍历输出集合中每个元素的值
for i in 张三 李四 王五
do
echo $i 是个好人
done

测试结果
在这里插入图片描述
例2:遍历用户指定输入的集合

#!/bin/bash
#遍历输出集合中每个元素的值
for i in $*
do
echo $i 是个好人
done

在这里插入图片描述
注意: $* 和$@都是获取用户输入的参数列表,但它们有略微的区别。
当脚本文件中的in后面的参数集不加双引号时,它们是没有区别的。但是如果in后面的参数集加了双引号,$*会把参数集作为一条数据,而$@仍会把参数集作为一个集合。

#!/bin/bash
#遍历输出集合中每个元素的值
echo '=======$*带引号======'
for i in "$*"
do
echo $i 是个好人
done
echo '=======$@带引号的结果集======'
for i in "$@"
do
echo $i 是个好人
done

在这里插入图片描述

5.while循环

1.基本语法

while [ 条件判断式 ] 
  do 
    程序
  donewhile((表达式))
do
	程序
done

例:计算1到100的和

#! /bin/bash
#计算1到100之间的和
sum=0
i=1
while(($i<=100))
do
   sum=$[$i+$sum]
   # linux中认为 i++是一个字符串,所以我们不能直接写成i++
   # 方式一: i=$[$i+1]
   # 方式二: let i++
  let i++
done
echo 1到100之间的和为:$sum

在这里插入图片描述

6.read(选项)(参数)

read(选项)(参数)
选项:
-p:指定读取值时的提示符;
-t:指定读取值时等待的时间(秒)。
参数
	变量:指定读取值的变量名

例:read -p 请输入参数 -t 10 num
表示:提示符为请输入参数,等待时间为10秒,若10秒内未接收到参数则退出。用户输入的参数用num接收。
在这里插入图片描述

四、函数

1.系统函数

[1]basename基本语法

basename [string / pathname] [suffix] (功能描述:basename命令会删掉所有的前缀包括最后一个(‘/’)字符,然后将字符串显示出来。
选项:
suffix为后缀,如果suffix被指定了,basename会将pathname或string中的suffix去掉。
例:截取/home/shell/while.sh路径的文件名称

[root@localhost shell]# basename /home/shell/while.sh 
while.sh
[root@localhost shell]# basename /home/shell/while.sh .sh
while
[root@localhost shell]#
[2]dirname基本语法
dirname 文件绝对路径(功能描述:从给定的包含绝对路径的文件名中去除文件名(非目录的部分),然后返回剩下的路径(目录的部分))

例:获取 /home/shell/while.sh 文件的路径

[root@localhost shell]# dirname /home/shell/while.sh 
/home/shell

2.自定义函数

基本语法

function  funname[()]
{
	Action;
	[return int;]
}
funname

注意:

  • 必须在调用函数地方之前,先声明函数,shell脚本是逐行运行。不会像其它语言一样先编译。
  • 函数返回值,只能通过$?系统变量获得,可以显示加:return返回,如果不加,将以最后一条命令运行结果,作为返回值。return后跟数值n(0-255)
    例:自定义一个执行两个参数的加法操作的函数
#!/bin.bash
#自定义一个执行两个参数的加法操作的函数
function add()
{
 result=$[$1+$2]
 echo 两数之和为:$result
 #如果没有定义return,返回函数中最后一条语句执行的返回值
 #return
}
#读取用户输入的参数作为函数的参数
read -p 请输入第一个参数: num1
read -p 请输入第二个参数: num2
add num1 num2

在这里插入图片描述

五、shell工具(重点)

1.wc

wc命令用来计算。利用wc指令我们可以计算文件的Byte数、字数或是列数,若不指定文件名称,或是所给予的文件名为“-”,则wc指令会从标准输入设备读取数据。

  1. 基本语法
wc [选项参数] filename
  1. 参数说明
选项参数功能
-l统计文件行数
-w统计文件的单词数
-m统计文件的字符数
-c统计文件的字节数

例:查看文件test01.sh中的信息
在这里插入图片描述
注意:

  • wc命令中,是以空格来区分单词的数量。案例中第一行注释没有空格,则认为它是一个单词。
  • wc命令不认为空格是字符

2.cut

cut的工作就是“剪”,具体的说就是在文件中负责剪切数据用的。cut 命令从文件的每一行剪切字节、字符和字段并将这些字节、字符和字段输出。

  1. 基本语法
    cut [选项参数] filename
    说明:默认分隔符是制表符
  2. 选项参数说明
选项参数功能
-ff为fileds,列号,提取第几列
-dd为Descriptor分隔符,按照指定分隔符分割列

例1:以:为间隔,切割PATH环境变量的第一列
在这里插入图片描述
例2:以:为间隔,切割PATH环境变量的第二、三列
在这里插入图片描述
例3:选取系统PATH变量值,第2个“:”开始后的所有路径:
在这里插入图片描述
例4:以:为间隔,切割PATH环境变量的第一到三列,和第五列
在这里插入图片描述

3.sed

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

  1. 基本用法
sed [选项参数]  ‘command’  filename
  1. 选项参数说明
参数选项功能
-e直接在指令列模式上进行sed的动作编辑。
  1. 命令功能描述
命令功能描述
a新增,a的后面可以接字串,在下一行出现
d删除
e查找并替换
  1. 数据准备
[root@localhost shell]# touch sed.txt
[root@localhost shell]# vim sed.txt
zhang san
li si
wang wu

w    w
zhao liu
tian qi
  1. 将“ni hao”这个单词插入到sed.txt第二行下,打印
[root@localhost shell]# sed '2a ni hao' sed.txt
zhang san
li si
ni hao
wang wu

w    w
zhao liu
tian qi

注意:文件并没有改变。操作的是流值的值

  1. 删除sed.txt文件第二行
    在这里插入图片描述
  2. 删除sed.txt文件最后一行
    在这里插入图片描述
  3. 删除sed.txt文件第二行至最后一行
    在这里插入图片描述
  4. 将sed.txt文件中w替换为S
    在这里插入图片描述
    注意:‘g’表示global,全部替换,不加g只会替换第一个匹配到的字符。
  5. 将sed.txt文件中的第二行删除并将w替换为S
    在这里插入图片描述

4.sort

sort命令是在Linux里非常有用,它将文件进行排序,并将排序结果标准输出。默认情况以第一个字符串的字典顺序来排序.

  1. 基本语法
    sort(选项)(参数)
选项说明
-n依照数值的大小排序
-r以相反的顺序来排序
-t设置排序时所用的分隔字符,默认使用TAB
-k指定需要排序的列
-uu为unique的缩写,即如果出现相同的数据,只出现一行

参数:指定待排序的文件列表.

准备数据

[root@localhost shell]# touch sort.sh
bb:40:5.4
bd:20:4.2
xz:50:2.3
cls:10:3.5
ss:30:1.6
  1. 按照“:”分割后的第三列倒序排序。
    在这里插入图片描述

5. awk

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

  1. 基本用法
    awk [选项参数] ‘pattern1{action1} pattern2{action2}…’ filename
    pattern:表示AWK在数据中查找的内容,就是匹配模式
    action:在找到匹配内容时所执行的一系列命令
  2. 选项参数说明
选项参数功能
-F指定输入文件折分隔符
-v赋值一个用户定义变量
  1. 案例
    数据准备,将/etc/password 拷贝至当前目录下
sudo cp /etc/passwd ./

例1: 搜索passwd文件以root关键字开头的所有行,并输出该行的第7列。

awk -F: '/^root/{print $7}' passwd 
结果: /bin/bash

例2:搜索passwd文件以root关键字开头的所有行,并输出该行的第1列和第7列,中间以“,”号分割。

 awk -F: '/^root/{print $1","$7}' passwd
 返回结果:root,/bin/bash

注意:只有匹配了patter的行才会执行action
例3:只显示/etc/passwd的第一列和第七列,以逗号分割,且在所有行前面添加列名user,shell在最后一行添加"zhangsan,/bin/lisi"

awk -F : 'BEGIN{print "user,shell"}{print $1","$7}END {print "zhangsan,/bin/lisi"}' passwd 
结果:
user,shell
root,/bin/bash
bin,/sbin/nologin
。。。
chrony,/sbin/nologin
rabbitmq,/sbin/nologin
zhangsan,/bin/lisi

注意:BEGIN 在所有数据读取行之前执行;END 在所有数据执行之后执行。
例4:将passwd文件中的用户id增加数值1并输出

awk -v i=1 -F: '{print $3+i}' passwd
结果:
1
2
3
4
5
。。。
  1. awk的内置变量
变量说明
FILENAME文件名
NR已读的记录数(行号)
NF浏览记录的域的个数(切割后列的个数)

例1 :统计passwd文件名,每行的行号,每行的列数

 awk -F: '{print "filename:" FILENAME",linenumber:"NR",columns:"NF}' passwd
结果:
filename:passwd,linenumber:1,columns:7
filename:passwd,linenumber:2,columns:7
filename:passwd,linenumber:3,columns:7
filename:passwd,linenumber:4,columns:7

例2 切割IP

ifconfig eth0 | grep "inet addr" | awk -F: '{print $2}' | awk -F " " '{print $1}'

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

 awk '/^$/{print NR}' sed.txt 
 结果:4

六、面试题

  1. Linux常用命令有哪些
参考答案:find、df、tar、ps、top、netstat等。(尽量说一些高级命令)
  1. Linux查看内存、磁盘存储、io 读写、端口占用、进程等命令
1、查看内存:top
2、查看磁盘存储情况:df -h
3、查看磁盘IO读写情况:iotop(需要安装一下:yum install iotop)、iotop -o(直接查看输出比较高的磁盘读写程序)
4、查看端口占用情况:netstat -tunlp | grep 端口号
5、查看进程:ps aux
  1. 使用Linux命令查询file1中空行所在的行号
awk '/^$/{print NR}' sed.txt
  1. 有文件chengji.txt内容如下:
    张三 40
    李四 50
    王五 60
    使用Linux命令计算第二列的和并输出
cat chengji.txt | awk -F " " '{sum+=$2} END{print sum}'
  1. Shell脚本里如何检查一个文件是否存在?如果不存在该如何处理?
#!/bin/bash

if [ -f file.txt ]; then
   echo "文件存在!"
else
   echo "文件不存在!"
fi
  1. 用shell写一个脚本,对文本中无序的一列数字排序
[root@CentOS6-2 ~]# cat test.txt
9
8
7
6
5
4
3
2
10
1
[root@CentOS6-2 ~]# sort -n test.txt|awk '{a+=$0;print $0}END{print "SUM="a}'
1
2
3
4
5
6
7
8
9
10
SUM=55
  1. 请用shell脚本写出查找当前文件夹(/home)下所有的文本文件内容中包含有字符”shen”的文件名称
grep -r "shen" /home | cut -d ":" -f 1
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值