本文共 11964 字,大约阅读时间需要 39 分钟。
shell编程:
shell的概念介绍:
1.1命令解释器:
shell是命令解释器(command interpreter),是Unix操作系统的用户接口,程序从用户接口得到的输入信息,shell将用户程序及其输入翻译成操作系统内核(kernel)能够识别的指令,并且操作系统内核执行完将返回的输出通过shell在呈现给用户,下图所示用户,shell,和操作系统之间的关系
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-L8Ujhb0I-1624872441787)(C:\Users\16326\Desktop\dayHomework\QQ截图20210624213540.png)]
(一个系统可以存在多个shell)
操作系统内核(kernal)与shell是独立的套件,而且都可以被替换;不同的操作系统使用不同的shell;同一个kernal之上可以使用不同的shell,也可以查看当前的shell是哪种:
Shell脚本:
Shell也是一门编程语言,即Shell脚本,在此脚本中,我们可以使用一些编程语法来进行一些任务操作,如:变量,类型,分支结构,循环结构,数组,函数等语法,在shell脚本中,必须指定一种shell命令解释器
Shell编程规范:
1.脚本文件的结构:
1.文件的扩展名必须是.sh2.文件的首行必须是#! 指定script的运行shell环境(即脚本解释器) 例如:#!/bin/bash3.脚本里的行注释符号为#4.指令,选项,参数之间即使有多个空格仍然会被视为一个空格5.tab键形成的空白也视为一个空格键6.空白行会被忽略
2.脚本文件的执行;
1.使用bash程序调用执行,只需要有读权限即可2.直接写script,必须要有rx权限才行3.借助变量Path功能
3.Shell的变量:
3.1变量的用法:
1.变量的命名规则: -命令只能使用英文字母,数字,下划线,首个字符不能以数字开头 -字母习惯使用大写 -中间不能有空格 -不能使用标点符号 -不能使用bash里的关键字,可以使用help命令查看保留关键字2.变量的使用规则: -直接定义变量名称,没有类型需要强调(类似于数学中:x=1,y=2,z=x+y) -赋值时,“=”前后不能有空格 -命令的执行结果赋值给变量时,使用反单引号 如time=`date` -调用变量时,必须使用$ 格式:$变量名 或者 ${变量名}
3.2变量的分类:
Linux Shell中的变量可以分为三种变量:局部变量,环境变量,特殊变量,可以通过set命令查看系统中存在的所有变量局部变量:也就是用户自定义的变量,在脚本中或者命令行中定义环境变量:保存和系统操作环境相关的数据,$HOME,$PWD,$SHELL,$USER等特殊变量: 一种是位置参数变量:主要用来向脚本中传递参数或者数据,变量名不能自定义,变量作用固定 一种是预定义变量:是bash中已经定义好的变量,变量名不能自定义,变量作用也是固定的
3.3局部变量:
用户自定义的变量由字母或者下划线开头,有字母,数字,下划线组成,并且大小写字母意义不同,变量名长度没有限制
1.定义变量:习惯上用大写字母来命名变量,变量名以字母表示的字符开头,不能用数字
2.调用变量:
2.1在使用变量的时候,要在变量名前加上前缀"$"
2.2使用echo,命令查看变量值
3.变量赋值:
第一种:定义时赋值:
#变量=值#注意:在上述的定义方式中,等号两边不能有空格[root@qianfeng01 ~]# str="hello qianfeng"[root@qianfeng01 ~]# a=9[root@qianfeng01 ~]# echo $a9[root@qianfeng01 ~]# echo $strhello qianfeng[root@qianfeng01 ~]# a=10[root@qianfeng01 ~]# echo $a10
第二种:将第一个命令的执行结果给变量赋值
[root@qianfeng01 ~]# A=`ll -a` --->反引号,运行里面的命令,并且把结果返回给变量A[root@qianfeng01 ~]# echo $A总用量 32 dr-xr-x---. 4 root root 159 6月 24 19:02 . dr-xr-xr-x. 17 root root 224 6月 24 15:30 .. -rw-------. 1 root root 1521 6月 22 18:55 anaconda-ks.cfg -rw-------. 1 root root 4691 6月 24 22:51 .bash_history -rw-r--r--. 1 root root 18 12月 29 2013 .bash_logout -rw-r--r--. 1 root root 176 12月 29 2013 .bash_profile -rw-r--r--. 1 root root 176 12月 29 2013 .bashrc -rw-r--r--. 1 root root 100 12月 29 2013 .cshrc drwxr-----. 3 root root 19 6月 24 19:02 .pki drwx------. 2 root root 57 6月 24 16:54 .ssh -rw-r--r--. 1 root root 129 12月 29 2013 .tcshrc-------------------------------------------------------------------------------------[root@qianfeng01 ~]# B=$(ll -a) --->等价于反引号[root@qianfeng01 ~]# echo $B总用量 32 dr-xr-x---. 4 root root 159 6月 24 19:02 . dr-xr-xr-x. 17 root root 224 6月 24 15:30 .. -rw-------. 1 root root 1521 6月 22 18:55 anaconda-ks.cfg -rw-------. 1 root root 4691 6月 24 22:51 .bash_history -rw-r--r--. 1 root root 18 12月 29 2013 .bash_logout -rw-r--r--. 1 root root 176 12月 29 2013 .bash_profile -rw-r--r--. 1 root root 176 12月 29 2013 .bashrc -rw-r--r--. 1 root root 100 12月 29 2013 .cshrc drwxr-----. 3 root root 19 6月 24 19:02 .pki drwx------. 2 root root 57 6月 24 16:54 .ssh -rw-r--r--. 1 root root 129 12月 29 2013 .tcshrc-------------------------------------------------------------------------------------[root@qianfeng01 ~]# aa=$((4+5))[root@qianfeng01 ~]# echo $aa9-------------------------------------------------------------------------------------[root@qianfeng01 ~]# bb=`expr 4+5`[root@qianfeng01 ~]# echo $bb4+5[root@qianfeng01 ~]# bb=`expr 4 + 5`[root@qianfeng01 ~]# echo $bb9
第三种:将一个变量的值赋给另一个变量:
[root@qianfeng01 ~]# echo $ahello world
4.变量叠加
#变量叠加,就是将两个字符串变量的值叠加在一起,类似于Java中的字符串拼接操作[root@qianfeng01 ~]# a=123[root@qianfeng01 ~]# echo $a123[root@qianfeng01 ~]# b="$a"456[root@qianfeng01 ~]# echo $b123456[root@qianfeng01 ~]# e=${a}456[root@qianfeng01 ~]# echo $e123456------------------------------------------------------------------------------------#单引号和双引号的区别:#现象:单引号里的内容会全部输出,而双引号里的内容会有变化#原因:单引号会将所有的特殊字符脱意[root@qianfeng01 ~]# num=10[root@qianfeng01 ~]# sum="$num hehe"[root@qianfeng01 ~]# echo $sum10 hehe[root@qianfeng01 ~]# sum2='$num hehe'[root@qianfeng01 ~]# echo $sum2$num hehe
删除变量:
#删除之前已经定义过了的变量,之后就无法再使用这个变量了#撤销变量a[root@qianfeng01 ~]# unset a#声明静态的变量 b=2,不能使用unset[root@qianfeng01 ~]# readonly b=2[root@qianfeng01 ~]# unset b-bash: unset: b: 无法反设定: 只读 variable
注意事项:
关于局部变量的作用域问题,用户自定义的局部变量,作用仅限于当前的shell环境,仅在当前的shell示例中有效,其他shell启动的程序不能访问局部变量
[root@qianfeng01 bin]# echo '#!bin/bash' > test.sh[root@qianfeng01 bin]# a=22[root@qianfeng01 bin]# echo $a22[root@qianfeng01 bin]# echo 'echo $A' >> test.sh[root@qianfeng01 bin]# echo $a22[root@qianfeng01 bin]# bash test.sh#打印结果为空,因为bash会开启一个新的shell进程
环境变量:
用户自定义的局部变量,只能在当前的shell和其所有的子shell中生效,如果把环境变量写进相应的配置文件,那么这个环境变量就会在所有的shell中生效
作用域:当前的shell以及所有的子shell
声明变量:export 变量名=变量值
定义环境变量的常见配置文件:
1./etc/profile ----> 针对系统所有的用户生效,此文件应用于所有用户每次登录系统时的环境变量定义,每次用户登陆的时候,都会加载这个文件
2. H O M E / . b a s h p r o f i l e − − − − − > 针 对 于 特 殊 的 用 户 生 效 , HOME/.bash_profile ----->针对于特殊的用户生效, HOME/.bashprofile−−−−−>针对于特殊的用户生效,HOME为用户的宿主目录,当这个用户登录的时候,首先加载/etc/profile文件中的定义,再加载$HOME/.bash_profile文件中的定义
位置参数变量:
变量 | 描述 |
---|---|
$n | n为数字表示第几个参数,$0表示命令本身,$1- 9 表 示 第 1 到 第 9 个 参 数 , 10 以 上 的 参 数 需 要 使 用 大 括 号 包 含 , 例 如 9表示第1到第9个参数,10以上的参数需要使用大括号{}包含,例如 9表示第1到第9个参数,10以上的参数需要使用大括号包含,例如{10} |
$* | 代表命令行中的所有参数,把所有参数看成一个整体,以“$1 2... 2... 2...n”的形式输出所有参数 |
$@ | 代表命令行中的所有参数,把每个参数区别对待,以"$1"" 2 " . . . . " 2"...." 2"...."n"的形式输出所有参数 |
$# | 参数的个数 |
@ 和 @和 @和*的区别:
1.他们都表示传递给函数或者脚本的所有参数,不被双引号包含时,都以"$1"" 2 " . . . " 2"..." 2"..."n"的形式输出所有参数
2.当他们被双引号包含时
2.1.“$*”会将所有的参数作为一个整体,以$1 $2 … $n的形式输出所有参数
2.2“$@”会将各个参数分开,以"$1"" 2 " . . . " 2"..." 2"..."n"的形式输出所有参数
预定义变量:
变量 | 描述 |
---|---|
$? | 执行上一个命令的返回值,执行成功,返回0;执行失败,返回非0 |
$$ | 当前进程的进程号(PID),即当前脚本执行时生成的进程号 |
$! | 后台运行的最后一个进程的进程号(PID),最后一个被放入后台执行的进程 |
read命令:
说明:read命令,可以从控制台读取用户输入的内容,并且给指定的变量进行赋值命令的基本格式为:read [option] variable常用option: -p:提示语句,在输入之前给用户提示信息 -n:显示输入的字符数量,到达这个数量的字符的时候,会自动地停止输入 -t:等待时间,单位为秒,当到达这个等待时间的时候,会自动地结束输入,并且不会读取任何输入的内容! 即,输入操作且回车,必须在执行的时间内完成 -s:隐藏输入的内容,在控制台上不显示任何输入的内容,常见于密码输入
注意事项:
1.在输入的时候,如果输入错了需要删除的时候,请使用ctrl+delete
2.符号不要输入中文
3.变量与之前的内容需要保持有空格
运算:
1.expr:
格式:expr m + n 或者 $((m+n)) 注意expr与运算符和变量之间要有空格sum=$((m+n)) 中=与$之间没有空格expr命令:对整数型变量进行算术运算(注意:运算符前后必须要有空格)
[root@qianfeng01 ~]# expr 3 + 58[root@qianfeng01 ~]# expr 3 - 5-2[root@qianfeng01 ~]# expr 3 / 50[root@qianfeng01 ~]# expr 3 % 53[root@qianfeng01 ~]# expr 3 \* 5 ------>*具有特殊含义,代表任意字符,所以需要使用转义字符\15[root@qianfeng01 ~]# echo $((3+5))8[root@qianfeng01 ~]# echo $((3-5))-2[root@qianfeng01 ~]# echo $((3/5))0[root@qianfeng01 ~]# echo $((3%5))3[root@qianfeng01 ~]# echo $((3*5))15
2. ( ) 与 ()与 ()与{}的区别
$()的用途和反引号``一样,用来表示优先执行的命令[root@qianfeng01 ~]# echo $(ls /root)anaconda-ks.cfg${ }作用是用来取变量echo ${PATH}$((运算内容)) 用于数字运算
字符串
1.字符串的脚本用法: 字符串不能单独使用,必须要配合变量 字符串可以使用单引号[' '],也可以使用双引号[" "],也可以不使用引号 单引号内的任意字符没有任何意义,都回原样输出 单引号内使用变量是无效的,单引号内不能出现单引号 双引号内可以使用变量 双引号内可以使用转义字符 在字符串拼接操作的时候我们可以进行无缝拼接,或者是在双引号里使用变量
2.字符串的长度 可以使用${#variable}或者expr length "${variable}"示例:#!/bin/bashvar='welcome to China'length1=${#var}length2=$(expr length "${var}")length3=`expr length "$var"`echo $length1echo $length2echo $length3
shell数组:
1.数组的使用规则:
在/bin/bash这个shell中,只有一维数组的概念,并且不限制数组的长度数组的元素是从0开始的获取数组的元素要使用下标下标使用不当,会报错
2.数组的定义:
定义格式:variable=(值1,值2,... 值3)注意:元素之间除了使用空格作为分隔符,还可以使用换行符或者name[0]=值1name[1]=值2...name[n]=值n
3.读取数组:
${variable[index]} 读取index索引上的元素${variable[*]} 读取所有元素${#variable[*]}或者${#variable[@]} 获取数组的长度
[root@qianfeng01 ~]# cat test3.sh#!/bin/bashcitys=(chen heng wen tian yuan)hobby[0]=readhobby[1]=filmhobby[2]=musicecho ${citys[0]}echo ${hobby[*]}echo ${#hobby[@]}[root@qianfeng01 ~]# bash test3.shchenread film music3
test测试命令:
文件检测类型:
test -e filename | 检测filename是否存在 |
---|---|
test -d filename | 检测filename是不是目录 |
test -f filename | 检测filename是不是普通文件 |
test -L filename | 检测filename是不是软链接文件 |
文件属性检测:
test -r filename | 检测filename是否有可读权限 |
---|---|
test -w filename | 检测filename是否有可写权限 |
test -x filename | 检测filename是否有执行权限 |
两个文件的比较:
test file1 -nt file2 | 检测file1是否比file2新 |
---|---|
test file1 -ot file2 | 检测file1是否比file2旧 |
test file1 -ef file2 | 检测file1和file2是否为同一文件 |
两个整数进行比较:
test n1 -eq n2 | 检测n1与n2是否相等 |
---|---|
test n1 -ne n2 | 检测n1与n2是否不等 |
test n1 -gt n2 | 检测n1是否大于n2(greater than) |
test n1 -lt n2 | 检测n1是否小于n2(less than) |
test n1 -ge n2 | 检测n1是否大于等于n2 |
test n1 -le n2 | 检测n1是否小于等于n2 |
里那个字符串进行比较:
test -z string | 检测string是否为空 |
---|---|
test -n string | 检测string是否不为空 -n 可以省略 |
test string1 == string2 | 检测string1与string2是否相等 |
test string1 != string2 | 检测string1与string2是否不相等 |
多条件连接:
test -r filename -a -x filename | and,两个检测都成立,返回true |
---|---|
test -r filename -o -x filename | or,只要有一个成立,就返回true |
test ! r filename | 非 |
1.通常来说test命令不单独使用,而是与if语句连用,或者是放在循环结构中
2.判断符号[]
除了好用的test之外,我们还可以使用中括号来进行检测条件是否成立
条件控制:
if条件语句-单分支
if [条件判断]then 条件成功时执行逻辑fi
if [条件判断];then 条件成立时的逻辑fi
#!/bin/basha=$1if($a == "true")then echo "hello world"fi
注意事项:
1.if语句需要使用fi结尾,和一般的语言使用大括号结尾不同
2.[条件判断] 就是用test命令进行判断,所以中括号和条件判断之间必须要有空格
3.then后面跟符合条件之后执行的程序,可以放在[]之后,用;分隔,也可以换行写入,就不需要;了
4.if与中括号之间必须要有空格
if条件语句-多分支
if [条件判断1]then 当条件判断1成立之时,执行程序1elif [条件判断2]then 当条件判断式2成立之时,执行程序2else 当所有条件都不满足时,执行此程序fi
示例:
编写⼀个坐⻋脚本,要求:脚本名字: home.sh逻辑: 从外⾯传⼊⼀个参数,根据参数判断: 1. 坐⻜机,2. 坐⽕⻋,3. 坐⽕箭,4.不回了[root@qianfeng01 myShell]# cat test6.sh#!/bin/bashread -p "please input your choice:" choiceif [ $choice == 1 ] #当然也可以使用test,括号中的内容换成 $choice -eq 1then echo "坐飞机"elif [ $choice == 2 ]then echo "坐火车"elif [ $choice == 3 ]then echo "坐火箭"else echo "不回了"fi
case:
在java中我们学过了switch-case这种结构,这种结构, 我们可以捕获一个变量的值,对这个变量取到的某些值进行不同的处理,在Shell中 ,也有类似的结构,就是casecase命令是一个多分支的if/else命令,case变量的值用来匹配value1,value2,value3等不同的值-匹配到之后,执行后面的命令,直到遇到双分号为止-类似于if命令,case命令使用esac作为终止符-case行尾必须为单词in-每个分支必须以右括号结束-匹配模式中可以使用方括号表示一个连续的范围,如[0-9];使用“|”表示或
#case的格式CMD=$1case $CMD in-------case行尾必须为 变量 in 表示捕获这个变量的值start)-------需要匹配到的值,需要以右括号作为结尾 echo "starting"匹配到之后,执行的逻辑语句,即一个分支 ;;--------一个分支的逻辑,需要以;;作为结束,不会向下穿透stop) echo "stopping" ;;*)---------*表示以上的分支都不满足的情况,类似于switch-case中的default echo "please using start|stop" ;;esac---------case语句,需要使用esac结束
#!/bin/bashcase $1 in"1") echo "周一";;"2") echo "周二";;"3") echo "周三";;"4") echo "周四";;"5") echo "周五";;"6") echo "周六";;"7") echo "周日";;esac
循环:
for循环:
for循环命令用来在一个列表条目中执行有限次数的命令 比如:你可能会在一个姓名列表或者文件列表中循环执行同一个命令for命令后紧跟着一个自定义变量,一个关键字in和一个字符串列表(可以是变量)第一次执行for循环的时候,字符串列表的第一个字符串会赋值给自定义变量,然后执行循环命令,直到遇到done语句;第二次执行for循环的时候,会右推字符串列表中的第二个字符串给自定义变量以此类推,知道字符串列表遍历完
方式一:
for N in 1 2 3do echo $Ndone--------------------------------------------------------------------------------for N in 1 2 3 ;do echo $N;done--------------------------------------------------------------------------------for N in { 1..3};do echo $N;done--------------------------------------------------------------------------------for N in { 1,2,3};do echo $N;done
方式二:
for((i = 0; i <= 5; i++))do echo $idone--------------------------------------------------------------------------------for((i = 0; i <= 5; i++));do echo $i ;done
while循环:
while命令根据紧跟其后的命令(command)来判断是否执行while循环,当command执行后的返回值(exit status)为0时,则执行while循环语句块,直到遇到done语句,然后再返回到while命令,判断command的返回值,当得到返回值为非0时,则终止while循环
第一种:
while [ expression ]do commanddone
第二种:
while((expression))do command ...done
函数:
1.函数代表着一个或者一组命令的集合,表示一个功能模块,常用于模块化编程2.以下是关于函数的一些重要说明: 在Shell中,函数必须先定义,再调用 使用return value来获取函数的返回值 函数在当前shell中执行,可以使用脚本中的变量
函数名(){ 命令一 命令二 return 返回值变量}结构:[ function ] funname [ () ]{ action; [return int;]}function start() / function start / start()
注意事项:
如果返回值后面没有(),在函数名和{之间,必须要有空格以示区分。函数返回值,只能通过$?,系统变量获取,可以显示加:return 返回值如果不加return 将以最后一条命令的运行结果作为返回值return后面的内容以字符串的形式写入,但是执行时会自动转换成数值类型,范围:数值n[0-255]
脚本测试:
-x:执行脚本,并显示所有变量的值
-n:不执行脚本,只是检查语法,将返回所有语法错误,例如函数没有正确闭合等
-v:执行并显示脚本内容
on ]
do command done第二种:```shellwhile((expression))do command ...done
函数:
1.函数代表着一个或者一组命令的集合,表示一个功能模块,常用于模块化编程2.以下是关于函数的一些重要说明: 在Shell中,函数必须先定义,再调用 使用return value来获取函数的返回值 函数在当前shell中执行,可以使用脚本中的变量
函数名(){ 命令一 命令二 return 返回值变量}结构:[ function ] funname [ () ]{ action; [return int;]}function start() / function start / start()
注意事项:
如果返回值后面没有(),在函数名和{之间,必须要有空格以示区分。函数返回值,只能通过$?,系统变量获取,可以显示加:return 返回值如果不加return 将以最后一条命令的运行结果作为返回值return后面的内容以字符串的形式写入,但是执行时会自动转换成数值类型,范围:数值n[0-255]
脚本测试:
-x:执行脚本,并显示所有变量的值
-n:不执行脚本,只是检查语法,将返回所有语法错误,例如函数没有正确闭合等
-v:执行并显示脚本内容
转载地址:https://blog.csdn.net/m0_56433040/article/details/118308454 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!