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

it2023-02-27  95

一、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 编辑该文件,内容如下 保存并退出 执行该文件的三种方式

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

6.脚本的编写要求

声明: #!/bin/bash正文: 必须是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,所有定义的变量也不会存在!

重新连接后,该变量消失 注意:

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

4.特殊变量

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

5.运算符

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

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

[2]案例
计算3+2的值 [atguigu@hadoop101 datas]# expr 2 + 3 5 计算3-2的值 [atguigu@hadoop101 datas]# expr 3 - 2 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]常用判断条件
两个整数之间比较 = 字符串的比较,判断两个字符串是否相等. = 两侧要有空格 -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 按照文件权限进行判断 -r 有读的权限(read) -w 有写的权限(write) -x 有执行的权限(execute) 例:判断test01.sh是否具有写权限 [ -w test01.sh ] echo $? 返回结果为0 即true 按照文件类型进行判断 -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指令会从标准输入设备读取数据。

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

例:查看文件test01.sh中的信息 注意:

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

2.cut

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

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

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

3.sed

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

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

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

删除sed.txt文件第二行 删除sed.txt文件最后一行 删除sed.txt文件第二行至最后一行 将sed.txt文件中w替换为S 注意:‘g’表示global,全部替换,不加g只会替换第一个匹配到的字符。将sed.txt文件中的第二行删除并将w替换为S

4.sort

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

基本语法 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 按照“:”分割后的第三列倒序排序。

5. awk

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

基本用法 awk [选项参数] ‘pattern1{action1} pattern2{action2}…’ filename pattern:表示AWK在数据中查找的内容,就是匹配模式 action:在找到匹配内容时所执行的一系列命令选项参数说明 选项参数功能-F指定输入文件折分隔符-v赋值一个用户定义变量 案例 数据准备,将/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 。。。 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

六、面试题

Linux常用命令有哪些 参考答案:find、df、tar、ps、top、netstat等。(尽量说一些高级命令) Linux查看内存、磁盘存储、io 读写、端口占用、进程等命令 1、查看内存:top 2、查看磁盘存储情况:df -h 3、查看磁盘IO读写情况:iotop(需要安装一下:yum install iotop)、iotop -o(直接查看输出比较高的磁盘读写程序) 4、查看端口占用情况:netstat -tunlp | grep 端口号 5、查看进程:ps aux 使用Linux命令查询file1中空行所在的行号 awk '/^$/{print NR}' sed.txt 有文件chengji.txt内容如下: 张三 40 李四 50 王五 60 使用Linux命令计算第二列的和并输出 cat chengji.txt | awk -F " " '{sum+=$2} END{print sum}' Shell脚本里如何检查一个文件是否存在?如果不存在该如何处理? #!/bin/bash if [ -f file.txt ]; then echo "文件存在!" else echo "文件不存在!" fi 用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 请用shell脚本写出查找当前文件夹(/home)下所有的文本文件内容中包含有字符”shen”的文件名称 grep -r "shen" /home | cut -d ":" -f 1
最新回复(0)