zoukankan      html  css  js  c++  java
  • Linux shell编程

    Linux shell编程

    本文大部分内容来源于《边干边学Linux内核指导》

    变量

    环境变量

    环境变量大多数在/etc/profile文件中初始化,该文件在用户登录时候执行

    所有的shell环境变量都会被传递给shell的子程序

    image-20200212103337212.png

    用户变量

    image-20200212103734626.png
    image-20200212103741361.png
    例如:

    image-20200212103838503.png
    这是对变量的声明,之后就可以使用等号为变量赋值(注意,一般情况下,变量可以直接赋值,不需要声明),注意等号前后没有空格,并且赋值的时候要注意符合类型要求:一个整型变量不能赋予非整型的值,非整型变量可以被赋予任何值

    如何删除变量呢?

    可以使用unset命令,或者显式地将值置为null也可(null是所有未声明的变量的状态)

    将命令的返回值赋值给变量

    1. 变量名=$(命令)
    2. 变量名=$(命令 [命令选项 ...] 参数1 参数2 ...)
    3. 或者:
    4. 变量名=命令``
    5. 变量名=命令 [命令选项 ...] 参数1 参数2 ...``

    变量引用

    由于是弱类型的变量,所以如果使用变量1=变量2的格式,需要区分是变量引用还是赋值,赋值的话需要在变量前面加一个$以取值

    image-20200212105057864.png
    一些关于取变量值的骚操作:

    image-20200212105141868.png

    命令

    命令替换

    image-20200212134905141.png

    用户输入

    image-20200212134941693.png
    image-20200212135105975.png

    参数传递

    image-20200212135552395.png
    image-20200212135813698.png
    可以注意到第一行是#! /bin/bash,它的作用是什么?

    来源:https://blog.csdn.net/iot_flower/article/details/69055590

    第一行的内容指定了shell脚本解释器的路径,而且这个指定路径只能放在文件的第一行。第一行写错或者不写时,系统会有一个默认的解释器进行解释。

    要证明这一点,可以在第一行乱写,执行看看会不会报错,我执行之后的结果是:

    image-20200212140730076.png
    要是读入的参数多于9个怎么办?其实这些参数都是被读入了的,可以echo $@来查看,只是不能用$1-$9表示罢了可以使用shift来将$1到$9表示的参数逻辑左移,就是原本$2表示的现在用$1表示,这样第十个参数就在$9中了,当然相应的$1中原本的参数除了$@之外能找到就没有表示的了

    这些位置参数的值可以通过set命令进行设置:

    image-20200212141736869.png
    注意,每次调用set命令,位置参数中的值都会被全部更新。如果传入参数不够9个,剩下的参数中的值就是null:

    image-20200212141842287.pngimage-20200212141852624

    这里有一个例子:

    image-20200212141937783.pngimage-20200212141947240

    ls -il $filename原本的输出是:

    image-20200212142025721.png

    控制逻辑

    if语句

    image-20200212142119542.png
    表达式中可以使用test命令做判断:

    image-20200212142334703.png
    test可以用一个方括号代替,这下shell脚本应该好看懂了吧

    常见的test条件:

    image-20200212142800675.png
    image-20200212142807605.png
    注意:image-20200212142927328.png

    for语句

    image-20200212144225410.png

    while语句

    image-20200212145427476.png
    这里举了一个密码检验的例子:

    image-20200212150137998.png

    until语句

    image-20200212150216053.png
    和while正好是反过来的,until语句中只要expression的判断为假,就会一直执行

    case语句

    image-20200212174124623.png
    image-20200212174147286.png
    加了;;并不代表它不会进入下一个判断,要是不想进入下一个判断的话要加break

    shell中也有breakcontinue,和C语言中的含义一致

    有一个例子很好地表示了它的作用,它可以用于处理用户输入的模糊性问题

    image-20200212174319225.png
    它可以借助或(|)操作符简化为:

    image-20200212174458661.png

    数制

    image-20200212175217768.png
    由此可知,shell中的运算是只支持整数的

    计算有三种方法:

    image-20200212175612388.png

    let

    image-20200212175630338.png
    **表示乘方运算,第一行运算中,如果等式前后没有空格,引号不加也没事

    $((expression))扩展

    注意这里的expression里和let中一样,计算的时候不需要加$符号

    image-20200212180231196.png
    image-20200212180247579.png

    expr

    其将参数作为表达式进行计算

    image-20200212204000342.png
    例如:

    image-20200212204241133.png

    自增和自减运算

    来源:https://blog.csdn.net/Jerry_1126/article/details/52336340

    在Shell脚本中,用于while或for循环中经常要涉及到整数自增的情况,下面罗列下可能的方式

    【方式一】declare -i来声明整数变量

    root@localhost:~# declare -i x=1
    root@localhost:~# x+=1
    root@localhost:~# echo $x
    2

    注意第一中必须先声明为整数,否则shell默认是当成字符串处理的,+=运算也默认是字符串拼接,结果就是:

    image-20200213102307297.png

    【方式二】使用let命令

    root@localhost:~# i=1
    root@localhost:~# let i+=1
    root@localhost:~# echo $i
    2

    方法二方便一些

    root@localhost:~# i=1
    root@localhost:~# let i=$i+1
    root@localhost:~# echo $i
    2
    root@localhost:~# i=1
    root@localhost:~# let i++
    root@localhost:~# echo $i
    2
    root@localhost:~# i=1
    root@localhost:~# let ++i
    root@localhost:~# echo $i
    2
    【方式三】使用(())

    root@localhost:~# i=1
    root@localhost:~# ((++i))
    root@localhost:~# echo $i
    2
    root@localhost:~# i=1
    root@localhost:~# ((i++))
    root@localhost:~# echo $i
    2
    【方式四】使用expr命令

    root@localhost:~# i=1
    root@localhost:~# i=expr $i + 1
    root@localhost:~# echo $i
    2
    root@localhost:~# i=1
    root@localhost:~# i=$(expr $i + 1)
    root@localhost:~# echo $i
    2
    【方式五】使用$(())
    root@localhost:~# i=1
    root@localhost:~# i=$(($i + 1))
    root@localhost:~# echo $i
    2
    【方式六】使用$[]
    root@localhost:~# i=1
    root@localhost:~# i=$[$i + 1]
    root@localhost:~# echo $i
    2
    备注:
    1)使用i=$(expr $i + 1)比i=expr $i + 1要好些

    2)使用(())或者$(())速度要比expr快

    3)如果不考虑速度问题,涉及到不同平台的兼容,最好使用expr

    4)Bash(sh)上使用比较多的情形:let,expr,(())

    数组

    shell中是数组不需要预先声明长度,元素也不需要连续赋值

    image-20200212204640310.png
    其他未赋值的部分还是null

    由上图可以看出,引用数组中元素的方式为:image-20200212204855378.png
    image-20200212204940713.png

    字符串

    分割字符串

    这几种方法都不能实现例如将"test"分割为"t""e""s""t"的功能,都要求有个分隔符

    来源:https://blog.csdn.net/u010003835/article/details/80750003

    方法一: 利用shell 中 变量 的字符串替换
    原理:

    ${parameter//pattern/string}

    用string来替换parameter变量中所有匹配的pattern

    参考文章: https://blog.csdn.net/u010003835/article/details/80749220

    示例:

    !/bin/bash

    string="hello,shell,split,test"
    array=(${string//,/ })

    for var in ${array[@]}
    do
    echo $var
    done

    img

    方法二: 设置分隔符,通过 IFS 变量
    原理

    自定义IFS变量, 改变分隔符, 对字符串进行切分

    参考文章:

    https://blog.csdn.net/whuslei/article/details/7187639

    一、IFS 介绍

    Shell 脚本中有个变量叫 IFS(Internal Field Seprator) ,内部域分隔符。完整定义是The shell uses the value stored in IFS, which is the space, tab, and newline characters by default, to delimit words for the read and set commands, when parsing output from command substitution, and when performing variable substitution.

    Shell 的环境变量分为 set, env 两种,其中 set 变量可以通过 export 工具导入到 env 变量中。其中,set 是显示设置shell变量,仅在本 shell 中有效;env 是显示设置用户环境变量 ,仅在当前会话中有效。换句话说,set 变量里包含了 env 变量,但 set 变量不一定都是 env 变量。这两种变量不同之处在于变量的作用域不同。显然,env 变量的作用域要大些,它可以在 subshell 中使用。

    而 IFS 是一种 set 变量,当 shell 处理"命令替换"和"参数替换"时,shell 根据 IFS 的值,默认是 space, tab, newline 来拆解读入的变量,然后对特殊字符进行处理,最后重新组合赋值给该变量。

    二、IFS 简单实例

    1、查看变量 IFS 的值。

    $ echo $IFS

    $ echo "$IFS" | od -b
    0000000 040 011 012 012
    0000004
    直接输出IFS是看不到的,把它转化为二进制就可以看到了,"040"是空格,"011"是Tab,"012"是换行符" " 。最后一个 012 是因为 echo 默认是会换行的。

    示例

    !/bin/bash

    string="hello,shell,split,test"

    对IFS变量 进行替换处理

    OLD_IFS="$IFS"
    IFS=","
    array=($string)
    IFS="$OLD_IFS"

    for var in ${array[@]}
    do
    echo $var
    done

    运行结果

    img

    方法三: 利用tr 指令实现字符替换
    原理

    由于只是对单个字符进行的替换,则可以用 echo args | tr "oldSpilt" "newSpilt" 的方式实现。

    tr 指令讲解

    背景介绍

    tr命令可以对来自标准输入的字符进行替换、压缩和删除。它可以将一组字符变成另一组字符,经常用来编写优美的单行命令,作用很强大。

    语法
    tr(选项)(参数)
    选项
    -c或——complerment:取代所有不属于第一字符集的字符;
    -d或——delete:删除所有属于第一字符集的字符;
    -s或--squeeze-repeats:把连续重复的字符以单独一个字符表示;
    -t或--truncate-set1:先删除第一字符集较第二字符集多出的字符。
    参数
    字符集1:指定要转换或删除的原字符集。当执行转换操作时,必须使用参数“字符集2”指定转换的目标字符集。但执行删除操作时,不需要参数“字符集2”;
    字符集2:指定要转换成的目标字符集。

    示例:

    !/bin/bash

    string="hello,shell,split,test"
    array=(echo $string | tr ',' ' ' )

    for var in ${array[@]}
    do
    echo $var
    done

    img

    退出码

    image-20200212174758292.png

    printf

    这里也有printf,可以用来替代echo

    但是由于shell的运算是不支持浮点数的,所以没有浮点数相关的计算

    There are被括住以成为一个字符串

    转义字符

    来源:https://blog.csdn.net/yujin2010good/article/details/78786482

    转义字符
    反斜线()是bash的转义字符,也叫逃逸字符或者转义字符。
    我们想让 通配符,或者元字符变成普通字符,不需要使用它。那么这里我们就需要用到转义符了
    实例:
    [root@sande-lvs01 ~]# echo 9 * 9 = 81
    9 1.txt anaconda-ks.cfg install.log install.log.syslog install.log.tar install.log.tar.zip zabbix-agent-3.0.4-1.el6.x86_64.rpm zabbix-agent-3.0.4-1.el6.x86_64.rpm.1 zabbix_agent.sh 9 = 81
    [root@sande-lvs01 ~]# echo 9 '' 9
    9 * 9
    [root@sande-lvs01 ~]# echo 9 '
    ' 9 = 81
    9 * 9 = 81
    [root@sande-lvs01 ~]# echo '9 * 9 = 81'
    9 * 9 = 81
    [root@sande-lvs01 ~]# echo 9 * 9 = 81
    9 1.txt anaconda-ks.cfg install.log install.log.syslog install.log.tar install.log.tar.zip zabbix-agent-3.0.4-1.el6.x86_64.rpm zabbix-agent-3.0.4-1.el6.x86_64.rpm.1 zabbix_agent.sh 9 = 81
    [root@sande-lvs01 ~]# echo 9 * 9 = 81
    9 * 9 = 81
    [root@sande-lvs01 ~]#一般特殊符号要出现必须用转义字符
    ' " * ? ~ ` ! # $ & |

    { } ; < > ^

    续行符号

    来源:https://blog.csdn.net/yujin2010good/article/details/78786482

    转义字符唯一的例外是:的后方,若是接续换行(不可见字符),即先输入,再敲回车。
    [root@sande-lvs01 ~]# echo "wolf
    > wolf"
    wolf wolf
    [root@sande-lvs01 ~]#

    函数

    image-20200212205052293.png
    image-20200212205107295.png
    例如:

    image-20200212205138597.png
    可以看到,调用函数的时候不需要加()

    传参时使用的是位置参数:

    image-20200212205346049.png
    例如:

    #!/usr/bin/env bash
    # encoding: utf-8.0
    
    function test_func()
    {
        echo "output from inside-function:test_func"
        echo 'input parameter1: '$1
        echo 'input parameter2: '$2
    }
    echo "here is main function"
    echo "now inside function: test_func"
    test_func hello world 
    

    函数可以访问全局变量,也可以使用local关键字定义局部变量

    函数也可以return返回参数的,这个参数被直接返回给函数调用的位置

    here文档

    image-20200212205852808.png
    [-]的方括号表示它是可选的

    input_marker是可以自定义的:

    image-20200212205943701.png
    image-20200212205950563.png
    image-20200212210003278.png
    例如上图的例子,就是借助cat命令实现向shell中大量输出的例子

    下图是在脚本中使用here文档维护目录并实现查找功能的一个例子:

    image-20200212210410468.png
    image-20200212210420341.png
    在查找的脚本中集成了数据

    exec命令

    image-20200212211106431.png
    image-20200212210820507.png
    这个例子能体现出”替换当前进程“的意思:

    image-20200212211705966.png
    image-20200212211719102.png

    trap命令

    这个命令的功能就是接受signal

    可以使用kill命令发送信号

    image-20200212221441794.png
    默认的处理方式一般都是终止当前进程

    例如:image-20200212221648291.png��是设置中断的处理方法是默认方法

    例如:

    image-20200212222155331.png
    image-20200212222206246.png
    image-20200212222216318.png

    调试脚本

    脚本对于错误是会报错并说明错误的行数的,对于简单问题直接使用echo打印变量值就可以了,对于复杂错误的话:

    image-20200212222355105.png
    也就是说,可以一开始使用命令行选项的方式对全脚本进行设置,但是如果只在错误代码附近设置可以得到更少的冗余信息,此时就可以使用set选项,也就是将它们加在错误代码的上下(上为开,下为关)

    表格中前三个,命令行选项和set选项的功能是一致的�

  • 相关阅读:
    关于PDF.NET开发框架对Mysql Sqlite PostgreSQL数据库分页支持的个人看法
    【山外转载】如何高效的学习技术
    【山外笔记-四级计算机网络】第1章 网络技术基础
    【山外笔记-云原生】《Docker+Kubernetes应用开发与快速上云》读书笔记-2020.04.25(六)
    【山外笔记-数据库】Memcached教程详解
    【山外问道】什么是UUID
    【山外问道】Linux UUID的查询方法
    【山外笔记-SVN命令】svnlook命令详解
    【山外笔记-SVN命令】svn命令详解
    【山外笔记-工具框架】SVN版本控制系统
  • 原文地址:https://www.cnblogs.com/jiading/p/12302600.html
Copyright © 2011-2022 走看看