欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  科技

shell脚本-基础

程序员文章站 2022-08-04 11:55:11
shell脚本 基础 编程基础 shell脚本说明 变量介绍 变量的作用: 数据暂存 参与运算 表示数据范围 强类型变量: 变量不经过强制转换,它永远是这个数据类型,不允许隐式的类型转换。 一般定义变量时必须指定类型、参与运算必须符合类型要求。 调用未声明变量会产生错误。 如 java,c 的变量 ......

shell脚本-基础

编程基础

    程序是指令+ 数据
    程序编程风格:
        过程式:以指令为中心,数据服务于指令
        对象式:以数据为中心,指令服务于数据
    shell 程序提供了编程能力,解释执行。
    计算运行二进制指令。
    编译执行:
        高级语言--> 编译器--> 目标代码
        如java,C#
    解释执行:
        高级语言--> 解释器--> 机器代码
        如shell, perl, python
        
    编程逻辑处理方式:
        顺序执行
        循环执行
        选择执行
    
    shell 编程:
        过程式、解释执行
        
    编程语言的基本结构:
        各种系统命令的组合
        数据存储:变量、数组等
        表达式: a + b等
        语句:if的等

shell脚本说明

    shell 脚本:
        包含一些命令或声明,并符合一定格式的文本文件
    shell 脚本的用途有:
        自动化常用命令
        执行系统管理和故障排除
        创建简单的应用程序
        处理文本或文件
    格式要求:
        首行shebang 机制
        #!/bin/bash
        #!/usr/bin/python
        #!/usr/bin/perl
        ....
        #! 就是告诉系统,这个脚本文件需要使用指定的命令解释器来执行。
        紧随 #!的是一个路径名,此路径指向用来解释此脚本的程序,它可以是shell,可以是程序设计语言,也可以是实用程序。
        这个解释器从头( #!的下一行)开始执行整个脚本的命令,同时忽略注释。 
    shell脚本的创建和运行:
        创建脚本:
            使用文本编辑器vim等来创建文本。
            第一行必须是shell声明序列#!,一般为#!/bin/bash。
            其余行为执行的命令。
            添加注释使用#,注释以#开头。
        运行脚本:
            给予执行权限,在命令行上指定脚本的绝对或相对路径
                chmod +x FILE.sh
                /PATH/TO/FILE.sh
            直接运行解释器,将脚本作为解释器程序的参数运行
                source or . +脚本,一般不这么用,这样会对当前环境进行影响
                bash + 脚本,就不会影响外部工作环境
    脚本规范:
        脚本代码开头约定
            1 、第一行一般为调用使用的语言
            2 、程序名,避免更改文件名为无法找到正确的文件
            3 、版本号
            4 、更改后的时间
            5 、作者相关信息
            6 、该程序的作用,及注意事项
            7 、最后是各版本的更新简要说明
        脚本开头的示例:
            #!/bin/bash
            #-------------------------------------------------
            #Filename:
            #Description:
            #Revision:
            #Date:
            #Author:
            #Email:
            #Phonenumb:
            #Copyright:
            #------------------------------------------------
        脚本结构:
            解释器:#!/bin/shell,等
            配置变量:自己定义的变量,A=123等
            功能描述:以#开头来说明接下来执行语句的作用
            执行命令:指令+参数,包括各种语句表达式等
    脚本调试:
        检测脚本中的语法错误
            bash -n /PATH/TO/FILE.sh
        调试执行
            bash -x /PATH/TO/FILE.sh
        脚本中默认不支持别名
            尽可能用命令的绝对路径

变量介绍

    变量的作用:
        数据暂存
        参与运算
        表示数据范围
    强类型变量:
        变量不经过强制转换,它永远是这个数据类型,不允许隐式的类型转换。
        一般定义变量时必须指定类型、参与运算必须符合类型要求。
        调用未声明变量会产生错误。
        如 java,c#的变量
    弱类型变量:
        语言的运行时会隐式做数据类型转换。
        无须指定类型,默认均为字符型。
        参与运算会自动进行隐式类型转换。
        变量无须事先定义可直接调用
        如bash,php的变量
    变量的命名规则:
        不能使程序中的保留字,如if、for等。
        只能使用数字、字母及下划线,且不能以数字开头。
        需见名知义。
        统一命名规则,即驼峰命名法
    bash中的变量种类
        根据变量的生效范围作为标准
        本地变量:   生效范围为当前shell进程。对当前shell之外的其它shell 进程,包括当前shell的子shell 进程均无效。
        环境变量:   生效范围为当前shell进程及其子进程。
        局部变量:   生效范围为当前shell进程中某代码片断( 通常指函数)。
        位置变量:   $1, $2, ...来表示,用于让脚本在脚本代码中通过调用命令行传递给它的参数,大于9的数,就应该加大括号:${10}
        特殊变量:   $?, $0, $*, $@, $#,$$
    本地变量
        变量赋值:
            name=value
        引用value:
            直接字串:   name=“root"
            变量引用:   name="$USER"
            命令引用:   name=` COMMAND `; name =$(COMMAND)
        变量引用:
            ${name}  
            $name   
            "  " :  弱引用,其中的变量引用会被替换为变量值
             '  ':  强引用,其中的变量引用不会被替换为变量值,而保持原字符串
            ${name[$i]} i是变量,name[$i]也是变量
            ' ':最傻的那个 ;" ":中间傻 ; ` `:聪明
        显示已定义的所有变量:
            set
        删除变量:
            unset name
    环境变量
        变量声明和赋值:
            export  name=VALUE
            declare -x  name=VALUE
        变量引用:
            $name, ${name},"$name"(尽量用带括和带双引号的)
        显示所有环境变量:
            env
            printenv
        bash内建的环境变量
            PATH,SHELL,USER,UID,HOME,PWD,SHLVL,LANG,MAIL,HOSTNAME,HISTSIZE,—
    只读变量
        只能声明,但不能修改和删除。
        声明只读变量:
            readonly name
            declare -r name
                先赋值再声明或者是声明赋值一起做,不然,声明过后就不能再赋值了
        查看只读变量:
            readonly –p
    位置变量
        在脚本代码中调用通过命令行传递给脚本的参数
        $1, $2, ... :   对应第1 、第2 等参数,是脚本后面跟着的参数,且9以后需要加大括号:${10}
        shift [n]   可以更换位置
        $0:     命令本身
        $*:     传递给脚本的所有参数,全部参数合为一个字符串
        $@:     传递给脚本的所有参数,每个参数为独立字符串
        $#:     传递给脚本的参数的个数
        $@与$*   只在被双引号包起来的时候才会有差异
        set - -     清空所有位置变量
        涉及到位置参数,脚本前面放置这个
            [ $# -lt 1 ] && echo "Usage:`basename $0` arg1... " && exit 10
            
    转换变量类型
        可以使用declare或者typeset来转换变量类型
            [root@localhost ~]# a=1;b=2;c=a+b;
            [root@localhost ~]# echo $c
            a+b
            [root@localhost ~]# typeset -i a;typeset -i b;typeset -i c;
            [root@localhost ~]# a=1;b=2;c=a+b;
            [root@localhost ~]# echo $c

退出状态

    进程使用退出状态来报告成功或失败
    0 代表成功,1 -255 代表失败
    $?变量保存最近的命令退出状态
    示例:
        ping -c1 -W1 hostdown &> /dev/null
        echo $?
    bash 自定义退出状态码
        exit [n]:自定义退出状态码
        注意:
            脚本中一旦遇到exit命令,脚本会立即终止;终止退出状态取决于exit 命令后面的数字
            如果未给脚本指定退出状态码,整个脚本的退出状态码取决于脚本中执行的最后一条命令的状态码

算术运算

    help let
    let arg [arg ...]
    运算
        +, -, *, /, % 取模(取余), ** (乘方)
        注:乘法符号有些场景中需要转义 , 如*
    增强型赋值:
        +=, -=, *=, /=, %=
    自增和自减:
        let var+=1
        let var++
        let var-=1
        let var--
    实现算术运算
        let var= 算术表达式
        var=$[ 算术表达式]
        var=$(( 算术表达式))
        var=$(expr arg1 arg2 arg3 ...)    ##expr判断后面的变量是否为整数,但不能为0。
        declare –i var =  数值
        echo ‘ 算术表达式’ | bc
        bc
        $RANDOM (0-32767)  ##bash内建的随机数生成器
            echo $[$RANDOM%50]  ##0-49 之间随机数

逻辑运算

    true和false
        1, 0
        输出0为假
        设置空为假
        设置0为真
    与:
        1  与 1 = 1
        1  与 0 = 0
        0  与 1 = 0
        0  与 0 = 0
    或:
        1 或  1 = 1
        1 或  0 = 1
        0 或  1 = 1
        0 或  0 = 0
    非:!
        ! 1 = 0
        ! 0 = 1
    短路运算
        短路与
        第一个为0 ,结果必定为0
        第一个为1 ,第二个必须要参与运算
        短路或
        第一个为1 ,结果必定为1
        第一个为0 ,第二个必须要参与运算
    
    异或:^
        异或的两个值, 相同为假,不同为真
        数值交换:       

shell脚本-基础

条件性执行操作符:&&和||

    根据退出状态而定,命令可以有条件地运行。
    &&  代表条件性的and、then,与
    || 代表条件性的or、else,或

条件测试:

    判断某需求是否满足,需要由测试机制来实现,专用的测试表达式需要由测试命令辅助完成测试过程
    评估布尔声明,以便用在条件性执行中
        若真,则返回0
        若假,则返回1
    测试命令和表达式
        test EXPRESSION    
        [ EXPRESSION ]
        [[ EXPRESSION ]]     ##支持扩展的正则表达式算法
        注意:
            EXPRESSION 前后必须有空白字符
            多测试在使用
            ![](http://images2017.cnblogs.com/blog/1250974/201802/1250974-20180207000632435-1219260200.png)
    
    数值测试:
        -gt (great than)    大于
        -ge (great equal)   大于等于
        -eq  (equal)    等于
        -ne (not equal) 不等于
        -lt (lower than)    小于 
        -le (lower equal)   小于等于
    字符串测试:
        ==  等于
        >   ascii 码大于ascii码 
        <   小于
        !=  不等于
        =~  左侧字符串能够被右侧的PATTERN所匹配
        -z  "STRING“ 字符串为空,空为真,不空为假
        -n  "STRING“ 字符串不空,不空为真,空为假
        注意:  
            此表达式一般用于[[ ]] 中;扩展的正则表达式。
            用于字符串比较时,用到的操作数STRING都应该使用引号。
    文件测试
        存在为真,不存在为假
        存在性和类别测试:
            -a|-e FILE:     是否文件存在
            -b FILE :   是否存在且为块设备文件
            -c FILE :   是否存在且为字符设备文件
            -d FILE :   是否存在且为目录文件
            -f FILE :   是否存在且为普通文件
            -h|-L FILE :    存在且为符号链接文件
            -p FILE :   是否存在且为命名管道文件
            -S FILE :   是否存在且为套接字文件
        文件权限测试:
            -r FILE :   是否存在且可读
            -w FILE:    是否存在且可写
            -x FILE:    是否存在且可执行
            测试的是实际权限,例如root就有大多数权限
        文件特殊权限测试:
            -u FILE :   是否存在且拥有suid 权限
            -g FILE :   是否存在且拥有sgid 权限
            -k FILE :   是否存在且拥有sticky 权限
        文件大小测试:
            -s FILE:    是否存在且非空
        文件是否打开:
            -t fd:  fd表示文件描述符是否已经打开且与某终端相关
            -N FILE:    文件自从上一次被读取之后是否被修改过
            -O FILE :   当前有效用户是否为文件属主
            -G FILE :   当前有效用户是否为文件属组
        双目测试:
            FILE1 -ef FILE2:    FILE1与FILE2 是否指向同一个设备上的相同inode
            FILE1 -nt FILE2:    FILE1是否新于FILE2 (mtime) 
            FILE1 -ot FILE2:    FILE1是否旧于FILE2
        
    组合测试
        命令
            COMMAND1 && COMMAND2     并且
            COMMAND1 || COMMAND2     或者
            ! COMMAND    非
            如:[[ -r FILE ]] && [[ -w FILE ]]
        表达式
            EXPRESSION1 -a EXPRESSION2      并且
            EXPRESSION1 -o EXPRESSION2      或者
            ! EXPRESSION    非
            必须使用测试命令进行
        示例:
            [ -z “$HOSTNAME” -o $HOSTNAME "=="localhost.localdomain" ] && hostname shen
            [ -f /bin/cat -a -x /bin/cat ] && cat /etc/fstab

括号的用法

    小括号()
        (子进程),小括号是开子进程了,开子shell,小括号内值,只能在括号内用。
    中括号[ ]
        [表达式],用于测试
    大括号{ }
        { cmd ; cmd ; …. ; }不会开子shell

参数导入:read

    使用read 来把输入值分配给一个或多个shell 变量。
    使用read 从标准输入中读取值,给每个单词分配一个变量,所有剩余单词都被分配给最后一个变量。
    示例:
        read -p “Enter a filename: “  FILE
        read a b c <<< "xxx yyy zzz"

展开命令行的优先级

    优先级从高到低
    把命令行分成单个命令词
    展开别名
    展开大括号的声明({}) 
    展开波浪符声明(~) 
    命令替换$() 和 (``) 
    再次把命令行分成命令词
    展开文件通配(* 、? 、[abc] 等等)
    准备I/0 重导向(< 、>) 
    运行命令

防参数属性扩展

    反斜线(\ )会使随后的字符按原意解释
        $ echo Your cost: \$5.00
        Your cost: $5.00
    加引号来防止扩展
        单引号(’ )防止所有扩展
        双引号(” )也防止所有扩展,但是以下情况例外:
            $ (美元符号)#变量扩展
             ` (反引号)#命令替换
            \ (反斜线) #禁止单个字符扩展
            ! (叹号)#历史命令替换

$- 变量

    echo $-
    himBH
    h:hashall ,
        打开这个选项后,Shell会将命令所在的路径hash下来,避免每次都要查询,通过set +h 将h 选项关闭。
    i:interactive-comments,
        包含这个选项说明当前的shell的是一个交互式的 shell ,所谓的交互式shell, 在脚本中i 选项是关闭的。
    m:monitor,
        打开监控模式,就可以通过Job control 来控制进程的停止、继续,后台或者前台执行等。
    B:braceexpand ,
        大括号扩展
    H:history ,
        H选项打开,可以展开历史列表中的命令,可以通过!感叹号来完成,例如“!!” 返回上最近的一个历史命令,“!n”第 返回第 n个历史命令