• shell脚本


    目录

    一、编程语言的分类

    二、shell

    【1】第一个shell脚本

    【2】常见的shell解析器

    【3】运行脚本的3种方式

    i)bash

    ii)source

    iii)直接给脚本添加可执行权限

    三、修改环境变量

    【1】如何查看系统提供的环境变量

    【2】查看PATH变量

    【3】修改PATH路径

    i)只对当前终端生效

     ii)只对当前用户生效 ---->修改家目录下的文件

    iii)对所有用户都生效的方式

    iv)对所有用户生效

    四、shell中的变量

    【1】定义变量

    【2】使用变量

    【3】变量的赋值

    五、shell中的数组

    【1】定义

    【2】数组中元素的访问 

    练习:

     【3】使用已有的数组给新的数组赋值

    六、shell中的输入输出

    【1】输出--->echo

     【2】read

    练习:

    七、shell中的算术运算

    【1】(())

    练习:

    【2】$[]实现算数运算

    练习:

    【3】let实现算数运算

    【4】expr

    练习:

    练习:

    八、shell中的分支语句

    【1】if···else分支

    余下见链接

    练习:


    一、编程语言的分类

    编译型语言:C、C++ ------>需要编译器

    解释型语言:shell、python ------>需要解析器

    二、shell

    shell---->贝壳

    shell解析器:起到保护内核的作用,用户无法直接和内核层交换,通过指令和shell解析器完成用户和内核的交互

    1. 应用层:代码
    2. --------------------------- shell解析器
    3. 内核层:
    4. 内核层的五大功能:
    5. 1、内存管理
    6. 2、网络管理
    7. 3、进程管理
    8. 4、文件管理
    9. 5、设备管理
    10. ---------------------------
    11. 硬件层:外部设备

    【1】第一个shell脚本

    hello.sh ---->后缀是.sh

    1. #!/bin/bash
    2. # #!---->shebang
    3. # 指明脚本运行使用的shell解析器
    4. #这是一行注释
    5. echo "第一个shell脚本"

    【2】常见的shell解析器

    bash:现在市面上大部分linux都使用bash解析器

    dash:比bash功能更少一点

    sh:和终端的交互性不好

    csh:类似C语言的模式

    如何查看本机使用的shell解析器:echo $SHELL

    【3】运行脚本的3种方式

    i)bash

    1. bash 文件名.sh ------>使用shell解析器去解析脚本
    2. bash在运行脚本时,会在后台打开一个新的终端,把运行的结果返回到当前终端

    ii)source

    source是一个终端指令

    source 文件名.sh source在同一个终端上运行和输出结果

    iii)直接给脚本添加可执行权限

    chmod 777 脚本名

    ./脚本名

    三、修改环境变量

    【1】如何查看系统提供的环境变量

    env ---->回显所有系统提供的环境变量

    【2】查看PATH变量

    echo $PATH

    PATH的作用,在终端执行指令或程序时,默认在PATH包含的路径中查找,如果程序/指令的路径不在PATH中,就会执行失败(未找到该命令)

    修改PATH之后,可以直接输入可执行程序名执行程序,不需要再加上路径

    【3】修改PATH路径

    一定不能修改原有的PATH路径

    i)只对当前终端生效

    1. export PATH=${PATH}:新的路径
    2. export PATH=${PATH}:/home/ubuntu/23061/day2
    3. export PATH = ${PATH} : /home/ubuntu/23061/day2
    4. | | | | | |
    5. 给(系统)变量赋值 要赋值的变量 赋值 拿到原有的PATH的值 路径分隔符 追加的新路径

     ii)只对当前用户生效 ---->修改家目录下的文件

    vim ~/.bashrc  --->打开用户的配置文件,把想要添加的路径使用export表达式添加到最后一行

    让配置文件生效:

    1. 重启(永久生效)
    2. source ~/.bashrc (临时生效) ------>使用source和.是同一个指令
    3. . ~/.bashrc (临时生效)

    iii)对所有用户都生效的方式

    修改/etc/environment

    sudo vim /etc/environment

    直接把想添加的路径,添加原有的路径后面

    让配置文件生效:

    1. 重启(永久生效)
    2. source /etc/environment (临时生效) ------>使用source和.是同一个指令
    3. . /etc/environment (临时生效)

    iv)对所有用户生效

    修改/etc/bash.bashrc

    1. sudo vim /etc/bash.bashrc
    2. 使用export表达式,将路径添加到最后

    让配置文件生效:

    1. 重启(永久生效)
    2. source /etc/bash.bashrc (临时生效) ------>使用source和.是同一个指令
    3. . /etc/bash.bashrc (临时生效)

    四、shell中的变量

    shell本身是擅长运行指令,shell是一个弱数据类型的语言

    【1】定义变量

    1. C中:
    2. 存储类型 数据类型 变量名;
    3. shell中:
    4. 变量=变量的值 ----->如果变量的值中间没有空格直接使用
    5. 变量='变量的值' ----->变量的值中间有空格
    6. 变量="变量的值" ----->使用一个已有的变量给新的变量赋值,并且赋值中有空格时
    7. ''内,$变量名,不会被展开

    注意:

    1. shell中等号两侧不允许有空格
    2. 如果有空格会把变量名识别成一个指令

    【2】使用变量

    1. 在shell中如果使用变量的值,需要给变量名前加$
    2. $变量名 ${变量名}

    【3】变量的赋值

    1. 1、使用已有的变量给新的变量赋值
    2. var1=hello
    3. var2=world
    4. var3="$var1 $var2"

    shell脚本的本质:命令的集合

    五、shell中的数组

    【1】定义

    1. C中
    2. int arr[4]={1,2,3,4};
    3. shell:
    4. 数组名=(1 2 3 4) ----->每个元素之间以空格作为分隔
    5. shell中支持稀疏数组
    6. 数组名=([下标]=初始值1 [下标]=初始值2 ·····)
    7. #!/bin/bash
    8. arr=(12 90 89 100)
    9. #shell中支持稀疏数组,下标不连续的数组
    10. brr=([0]=90 [3]=70 [7]=900)
    11. crr[0]=29 #给crr数组中下标为0的元素赋值
    12. crr[3]=78 #给crr数组中下标为3的元素赋值
    13. #再重新给brr中没有提供的下标的元素赋值
    14. brr[4]=67
    15. echo ${brr[4]}
    16. echo ${crr[3]}

    【2】数组中元素的访问 

    1. ${数组名[下标]}
    2. 访问数组中的所有元素
    3. ${数组名[*]}
    4. ${数组名[@]}
    5. ${#数组名[*]}
    1. #!/bin/bash
    2. arr=(12 90 89 100)
    3. #shell中支持稀疏数组,下标不连续的数组
    4. brr=([0]=,2 [3]=70 [7]=900)
    5. crr[0]=29 #给crr数组中下标为0的元素赋值
    6. crr[3]=78 #给crr数组中下标为3的元素赋值
    7. #再重新给brr中没有提供的下标的元素赋值
    8. brr[4]=67
    9. echo ${brr[@]}
    10. echo ${crr[*]}
    11. echo ${#brr[*]} #4 对于稀疏数组,#会记录数组中实际元素的个数
    12. echo ${#brr[0]} #2 对数组中的指定元素使用#,#记录元素中字符的个数

    练习:

    1、定义一个数组,使用外部参数给数组赋值,通过数组求外部参数的个数

    2、把家目录的下的所有文件名放到数组中,并记录家目录下文件的个数

    1. #!/bin/bash
    2. arr=($*) #把所有的外部参数赋值给数组arr
    3. echo ${#arr[*]}
    4. arr2=(`ls ~`) #把家目录的所有文件名赋值给数组arr1
    5. echo ${#arr2[*]}
    6. echo ${arr2[@]}

     【3】使用已有的数组给新的数组赋值

    1. #!/bin/bash
    2. arr1=(1 2 3 4)
    3. arr2=(b n m l)
    4. #定义一个数组arr3,使用原来的arr1和arr2给新数组arr3赋值
    5. arr3=(${arr1[*]} ${arr2[*]})
    6. echo ${arr3[@]} # 1 2 3 4 b n m l
    7. arr3=(${arr1[*]}${arr2[*]})
    8. echo ${arr3[@]} #1 2 3 4b n m l
    9. echo ${#arr3[*]}

    六、shell中的输入输出

    【1】输出--->echo

    echo默认不解析转义字符并且会自动换行

    -e:让echo指令解析转义字符

    -n:取消换行

    1. #!/bin/bash
    2. echo "111\n" #echo默认不解析转义字符,会默认换行
    3. echo -e "111\n" #111 换行两次
    4. echo "111\n" -e #111\n -e echo的参数不能放在最后一个位置,被识别成字符串
    5. echo -ne "111\n" #让echo取消换行,-n参数

     【2】read

    1. read 变量名
    2. read -s 变量名 ---->输入的内容不回显
    3. read -p "提示信息" 变量名 ----->-p回显提示信息
    4. read -n 字符个数 变量名 ----->控制输入的字符个数,当超过会自动停止
    5. read -t 秒数 变量名 ----->控制读入数据的时间,如果指定时间内不输入会自动停止
    6. read -a 数组名 ---->输入数组

    练习:

    1、尝试把read除了-a以外的参数结合起来使用

    1. #!/bin/bash
    2. #read -p "请输入一个变量" var
    3. #read -n 3 var
    4. #read -t 3 var
    5. #read -a arr
    6. read -sp "请输入一个变量" -n 3 -t 4 var
    7. #echo ${#arr[*]}
    8. echo $var

    七、shell中的算术运算

    shell本身不擅长算术运算,需要借助于运算符和其他指令

    (())     $[]    let    expr

    【1】(())

    常用于shell中整数的算术运算

    (())几乎支持所有的C语言语法,支持shell中的幂运算 **

    使用方法:

    1. ((表达式1,表达式2,表达式3,····))每一个表达式都会执行,取到最后一个表达式的结果
    2. (())内使用变量时,可以加$也可以不加$
    3. (())内的运算符两侧,可以有空格也可以没有空格
    4. 变量名=$((表达式)),获取(())的运算结果
    5. 可以直接在(())内进行赋值操作,((var1 = var1+var2))

    练习:

    1、终端输入两个三位数,将其中一个自增,把两个变量赋值给第二个变量相加并输出

    1. #!/bin/bash
    2. read -p "请输入两个变量" var1 var2 #如果同一行获取两个变量,变量中间放空格
    3. ((var1++)) #自增
    4. ((var2=var1+var2))
    5. echo $var1
    6. echo $var2
    7. ((var1=var1**3)) #对var1进行幂运算
    8. echo $var1

     2、求root用户的uid和ubuntu/linux用户gid相加的结果,比较这两个数的大小关系

    1. #!/bin/bash
    2. num1=`id -u root`
    3. num2=`id -g`
    4. echo $((num1+num2))
    5. #比较num1和num2的大小关系
    6. echo $((num1
    7. #比较num1和num2的大小关系
    8. echo $((num1

    【2】$[]实现算数运算

    使用方法: (仍然支持幂运算和自增自减运算)

    1. 变量名=$[表达式1,表达式2,表达式3,····],每一个表达式都执行,获取最后一个表达式的结果
    2. 运算时,运算符两侧可以有空格也可以没有空格
    3. 使用变量时,可以加$也可以不加$
    4. $[]本质上会遗留一个计算结果在,运算所在行,可以选择直接echo $[表达式] ,变量名=$[表达式]
    1. #!/bin/bash
    2. num1=100
    3. num2=30
    4. echo $[num1+num2] #直接在终端回显130
    5. echo $[num1++,num2**2,++num2] #31
    6. echo $num1 #101
    7. echo $num2 #31

    练习:

    1、计算当前目录下文件个数和家目录下文件个数的总和

    2、计算家目录下.c和.sh文件的和

    1. #!/bin/bash
    2. arr=(`ls`)
    3. arr1=(`ls ~`)
    4. brr=(`ls` `ls ~`) #把两个路径下的文件,放到同一个数组中
    5. crr=(${arr[*]} ${arr1[*]}) #先把两个路径下的文件分别存在不同数组中,再拼接两个数组
    6. num1=${#arr[*]}
    7. num2=${#arr1[*]}
    8. echo $[num1+num2]
    9. echo ${#brr[*]}
    10. echo ${#crr[*]}
    11. arr3=(`ls ~/*.c`)
    12. arr4=(`ls ~/*.sh`)
    13. #对前两行的数组计数
    14. num3=${#arr3[*]}
    15. num4=${#arr4[*]}
    16. echo $[num3+num4]

    【3】let实现算数运算

    使用方法:

    1. let 变量名=表达式 ----->let和变量名中间一定有空格
    2. let使用变量可以加$,也可以不加$
    3. let运算时,运算符两侧一定不能有空格
    4. let 表达式,运算是可以进行的但是没有办法接收运算的结果

     

    1. #!/bin/bash
    2. num1=100
    3. num2=30
    4. let ret=num2**2 #支持幂运算
    5. let num1++ #支持自增运算,但是不能接收表达式的结果
    6. echo $ret
    7. echo $num1 #101

    【4】expr

    expr是一条指令

    使用方法:

    1. expr使用变量的值时,必须加$
    2. 运算符两侧必须加空格 (不支持幂运算和自增自减运算)
    3. expr在使用时,一些字符需要转义,*,>,
    4. expr直接回显指令的执行结果到终端

    1. ARG1 | ARG2
    2. 如果ARG1的值不为0,结果就是ARG1,否则就是ARG2
    3. ARG1 & ARG2
    4. 如果RAG1和ARG2都不为0,结果是ARG1,否则是0
    5. ARG1 < ARG2
    6. ARG1 is less than ARG2
    7. ARG1 <= ARG2
    8. ARG1 is less than or equal to ARG2
    9. ARG1 = ARG2
    10. ARG1 is equal to ARG2
    11. ARG1 != ARG2
    12. ARG1 is unequal to ARG2
    13. ARG1 >= ARG2
    14. ARG1 is greater than or equal to ARG2
    15. ARG1 > ARG2
    16. ARG1 is greater than ARG2
    17. #!/bin/bash
    18. num1=-2
    19. num2=9
    20. : 'expr $num1 + $num2
    21. expr $num1 - $num2
    22. expr $num1 / $num2
    23. expr $num1 % $num2
    24. expr $num1 \* $num2
    25. '
    26. num3=0
    27. expr $num1 \| $num2
    28. expr $num1 \& $num2
    29. expr $num2 \> $num1
    30. expr $num2 != $num1
    31. expr $num2 = $num1

    练习:

    1、终端读入两个数据,使用expr比较大小关系

    2、计算/etc/group中,第20行组用户gid和第10行组用户gid的和

    1. #!/bin/bash
    2. read -p "请输入两个变量" var1 var2
    3. expr $var1 \>= $var2
    4. #获取/etc/group中第20行用户的gid
    5. num1=`head -20 /etc/group | tail -1 | cut -d : -f 3`
    6. #获取/etc/group中第10行用户的gid
    7. num2=$(head -10 /etc/group | tail -1 | cut -d : -f 3)
    8. expr $num1 + $num2

     expr对字符串的运算

    1. match str1 str2
    2. 返回str2在str1中完全匹配的个数(str2可以作为str1中子串)
    3. substr STRING POS LENGTH
    4. 如果字符串长度不够截取长度,就把字符串中所有的内容都截取出来
    5. 从string中的第pos个位置开始截取长度为length的子串(pos从1开始)
    6. index STRING CHARS
    7. 返回字符在字符串中第一次出现的位置,如果是多个字符,返回最先在字符串中出现的字符的下标
    8. (下标从1开始)
    9. length STRING
    10. 求字符串的长度
    1. #!/bin/bash
    2. str1=hello
    3. str2=hl
    4. expr match $str1 $str2 #0,因为hello中不能匹配到hl字符串
    5. expr substr $str1 2 3 #pos计数从1开始
    6. expr index $str1 lo #3l在hello最先出现
    7. expr length $str1
    8. expr length $str2

    练习:

    1、终端输入网址,如:www.baidu.com,要求:

    接触网址每个部分,并放入数组中,不能使用cut,使用expr解决

    1. #!/bin/bash
    2. read -p "请输入一个网址" net
    3. len=`expr length $net` #网址的长度
    4. #找第一个.的位置
    5. pos1=`expr index $net .`
    6. #截取第一个.前面的所有子串
    7. arr[0]=`expr substr $net 1 $((pos1-1))`
    8. #为了找第二个.需要把后面的所有子串都截取出来
    9. str2=`expr substr $net $((pos1+1)) $len`
    10. #找到第二个.的位置
    11. pos2=`expr index $str2 .`
    12. arr[1]=`expr substr $str2 1 $((pos2-1))`
    13. arr[2]=`expr substr $str2 $((pos2+1)) $len`
    14. echo ${arr[*]}

    八、shell中的分支语句

    【1】if···else分支

    1. []就是test指令
    2. #单分支结构
    3. if [ test语句 ] -----> if test 表达式
    4. then
    5. 语句块
    6. fi
    7. #双分支
    8. if [ test语句 ] -----> if test 表达式
    9. then
    10. 语句块
    11. else
    12. 条件不成立执行的语句块
    13. fi
    14. #多分支语句
    15. if [ test语句 ] -----> if test 表达式
    16. then
    17. 语句块
    18. elif [ test语句 ] ------> elif test 表达式
    19. then
    20. 条件不成立执行的语句块
    21. fi
    22. #!/bin/bash
    23. num1=90
    24. num2=300
    25. #if [ $num1 -le $num2 ]
    26. if test $num1 -le $num2
    27. then
    28. echo "num1<=num2"
    29. fi

    余下见链接

     https://blog.csdn.net/ck0056/article/details/132816564

    练习:

    写一个1.sh脚本,将以下内容放到脚本中:

    在家目录下创建目录文件,dir

    在dir下创建dir1和dir2

    把当前目录下的所有文件拷贝到dir1中,

    把当前目录下的所有脚本文件拷贝到dir2中

    把dir2打包并压缩为dir2.tar.xz

    再把dir2.tar.xz移动到dir1中

    解压dir1中的压缩包

    使用tree工具,查看dir下的文件

    1. #!/bin/bash
    2. mkdir ~/dir
    3. mkdir ~/dir/dir2 ~/dir/dir1
    4. cp * ~/dir/dir1/ -r
    5. cp *.sh ~/dir/dir2/
    6. tar -cJf ~/dir/dir2.tar.xz ~/dir/dir2/
    7. mv ~/dir/dir2.tar.xz ~/dir/dir1/
    8. tar -xvf ~/dir/dir1/dir2.tar.xz
    9. tree ~/dir

     

  • 相关阅读:
    《TCP/IP网络编程》阅读笔记--基于UDP的服务器端/客户端
    Spring 中不得不了解的姿势
    模板引擎Thymeleaf和监听器
    华为机试 - 水仙花数Ⅱ
    Java随笔-HTTP
    事务的隔离级别
    副本机制在kafka中的实践
    49. Group Anagrams
    力扣(LeetCode)272. 最接近的二叉搜索树值 II(2022.09.29)
    股票交易接口dll代码分享
  • 原文地址:https://blog.csdn.net/ck0056/article/details/132745232