滚滚红尘56

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

基础编程
    1. 创建
        在文件的第一行指定要使用的运行方式      #!/bin/bash
        系统会按照第一行!后指定的运行方式运行整个文件内容。
        如果不写的话,系统可能会按照当前登录的shell执行,但只是可能,Ubuntu系统很可能出问题。
        所以第一行指定运行方式是一种良好的习惯。
    2. 显示与输入
        输入
            read命令     等待用户的输入,并将获取的数据存到一个变量中
                read -p “Enter your name: ”name
                其他参数:
                    -t     指定超时时间
                    -s     隐藏方式读取
        显示
            echo “hello world”            自动动添加换行符
                控制输出不换行:        -n 参数
                让特殊转义符起作用        -e 参数
                    转义符一览
                        \b 其后有字符时,作为退格键
                        \c 取消输出行末的换行符
                        \e ESCAPE 键
                        \f 换行后连接上一行的结尾
                        \v 垂直制表符
                        \n 换行符
                        \r 光标移至行首
                        \t 制表符,也就是 Tab 键
            printf “hello %s %f\n” world 11.11        不自动换行,需要手动加\n,使用类似C语言printf
                printf  可以使用%对输出间距进行控制 使用间距控制,我们不用再担心显示输出时因变量长度的不确定性导致的混乱问题
                    %-10s        左对齐,显示宽度为10个字符的字符串,不足使用空格补齐
                    %10s        右对齐,显示宽度为10个字符的字符串,不足使用空格补齐
                    %10.2f        右对齐,显示宽度为10个字符的浮点数,小数点后面保留两位
        
        重定向
            输入和输出进程在Linux也是以文件的概念存在
            Linux用文件描述符来标识每个文件对象,它是一个非负整数
            每个进程一次最多可以有九个文件描述符(可以理解为指针变量),而bash shell保留了前3个。
                文件描述符        缩写            描述
                    0            STDIN            标准输入
                    1            SIDOUT            标准输出
                    2            SIDERR            错误输出
            符号(可以理解为把符号左边的内容传送到右边)
                覆盖    >
                追加    >>
            临时重定向与永久重定向
                临时
                    将标准输出重定向到文件    Command    >    file
                    将错误输出重定向到文件    Command    2>    file
                    将所有输出重定向到文件    Command >file 2>file    或者    Command &>file
                永久
                    exec命令:        exec 1>file
                    exec命令会在脚本执行期间保持设定的重定向策略
                    永久重定向之后想再改回来怎么办?可以使用后6个自定义文件描述符
                        exec 3>&1
                        exec 1>file
                        exec 1>&3
            既要显示又要存到文件
                tee filename        覆盖
                tee –a filename     追加    
        高级显示控制    使用SGR转义码
            格式为                 CSI[nm
            CSI 代表转义标志字符
                实际上就是ESC的ASCII值
                产生方法:
                    Linux下编辑时的产生方法
                        Ctrl+v 后按 ESC            Linux系统显示为 ^[
                    非Linux下编辑时的产生方法
                        \033                echo 需配合-e参数
                        echo -e  "hello \033[31;47mworld\033[0m"
            m 代表此语句为SGR转义码
            [ 半中括号为固定格式作为分隔
            n 代表控制码,可以有多个,使用 ; (分号)进行分隔
                    效果控制码                                                  颜色控制码
                    代码    描述                                                 两    代码    描述
                    0        重置为普通模式                                位    0        黑色
                    1        设置为强亮度                                    数    1        红色
            一    2        设置为弱亮度                                    3x    2        绿色
            位    3        使用斜体                                      前    3        黄色
            数    4        使用单下划线                                    景    4        蓝色
            字    5        使用慢闪烁                                       4x    5        洋红色
                    6        使用快闪烁                                       背    6        青色
                    7        背景色和前景色反转                         景    7        白色
                    8        将前景色设置为背景色(文字不可见   色
    3. 变量
        使用变量的方法:
            1. $variable        美元符号后紧跟变量名
            2. ${variable}        使用大括号
            以上两种方法没有本质区别。
                使用大括号的优点是:可以在调用变量后紧跟字符
                比如:        $ab        表示变量ab的值,而${a}b 表示变量a的值后紧跟b字符
        命令替换:
            1. $( )            美元符号后加小括号
            2. ``            反引号
            小括号和反引号中的字符会作为运行命令,其输出值作为返回值。
            
        环境变量:
            存储有关shell会话和工作环境的信息。
            这项特性允许你在内存中存储数据,是存储持久数据的一种简便方法。
        用户自定变量:
            定义方法:
                变量名=value        变量名='value'        变量名="value"
            注意事项:    等号两边不能有空格
        特殊变量:
            $0                执行时脚本本身的路径与名称
            $1 ~ $n            表示脚本的第n个参数
            $#                脚本运行时携带的命令行参数的个数
            $*                脚本的所有参数组成一个单词
            $@                脚本的所有参数当做一个字符串的独立单词
            $?                上一个命令的执行状态
            $$                脚本运行的当前进程的ID号
            $!                后台运行的最后一个进程的ID号
        局部变量
            使用普通方式定义的变量都是全局变量
            如果要在函数中定义局部变量,需要使用 local 关键字
        数组
            定义方法:
                array=(one two three four five)
            使用:
                echo “${array[2]}”
            删除:
                删除单个值         unset  ${array[2]}
                删除整个数组     unset  array  
    4. 结构化命令
        if命令
            if command            或     if command;then
            then                
                command                    
            elif                或    elif;then
                command
            else
                command
            fi
            Command 部分是Linux下的命令,而if测试的是此命令执行完毕的退出码
            使用格式     test condition        可以测试其他的条件,比如数值比较之类
                linux提供了test命令的简便用法    [(空格)  待比较条件 (空格)] 代替test命令
                使用示例:
                    If [ $a –eq 1 ]
                condition部分分类
                    数值比较            
                    -eq                         等于
                    -ne                         不等于
                    -gt                          大于
                    -lt                           小于
                    -ge                         大于等于
                    -le                          小于等于
                    
                    字符串比较
                    -z Str                          “Str” 的长度为零则为真。 [ -z "$aaa" ] [[ -z $aaa]]
                    [ -n Str ] or [ Str ]        “Str” 的长度为非零 non-zero则为真。
                    [ Str1 == Str2 ]            如果2个字符串相同则为真。
                    [ Str1 != Str2 ]             如果字符串不相等则为真。
                    [ Str1 < Str2 ]              如果 “Str1” sorts before “Str2” lexicographically in the current locale则为真。
                    [ Str1 > Str2 ]              如果 “Str1” sorts after “Str2” lexicographically in the current locale则为真。
                    
                    文件比较
                    -a FILE             如果 FILE 存在则为真
                    -b FILE             如果 FILE 存在且是一个块文件则为真。
                    -c FILE             如果 FILE 存在且是一个字特殊文件则为真。
                    -d FILE             如果 FILE 存在且是一个目录则为真
                    -e FILE             如果 FILE 存在则为真
                    -f FILE              如果 FILE 存在且是一个普通文件则为真
                    -g FILE             如果 FILE 存在且已经设置了SGID则为真。
                    -h FILE             如果 FILE 存在且是一个符号连接则为真
                    -k FILE             如果 FILE 存在且已经设置了粘制位则为真
                    -p FILE             如果 FILE 存在且是一个管道则为真
                    -r FILE             如果 FILE 存在且是可读的则为真
                    -s FILE             如果 FILE 存在且大小不为0则为真
                    -t FD                如果文件描述符打开且指向一个终端则为真
                    -u FILE             如果 FILE 存在且设置了SUID则为真
                    -w FILE             如果 FILE 存在且是可写的则为真
                    -x FILE             如果 FILE 存在且是可执行的则为真
                    -O FILE             如果 FILE 存在且属有效用户ID则为真
                    -G FILE             如果 FILE 存在且属有效用户组则为真。
                    -L FILE             如果 FILE 存在且是一个符号连接则为真
                    -N FILE             如果 FILE 存在并已经被修改 如果ied since it was last read则为真
                    -S FILE             如果 FILE 存在且是一个套接字则为真。
                    FILE1 -nt FILE2     如果 FILE1比FILE2新或 FILE1 存在 FILE2 不存在则为真
                    FILE1 -ot FILE2     如果 FILE1 比 FILE2 要老,或者 FILE2 存在 FILE1 不存在则为真
                    FILE1 -ef FILE2     如果 FILE1 和 FILE2 指向相同的设备和节点号则为真
            复合条件测试: []&&[]    []||[]
            双括号    (( expression ))
                Expression 中除了支持之前提到的比较运算符,还提供了如下预算符
                val++        后增
                val--        后减
                ++val        先增
                --val        先减
                !            逻辑求反
                ~            位求反
                **            幂运算
                <<            左移
                >>            右移
                &            按位与
                |            按位或
                &&            逻辑与
                ||            逻辑或
            双方括号 [[ expression ]]
                提供了字符串比较的高级特性
                特殊字符不需要转义( >, >>, <, <<等  )
                可以进行模式匹配
                    if [[ $USER == r* ]]
        case命令
            case variable in
            pattern1 | pattern2)
                commands0
                commands1;;
            pattern3)
                commands2;;
            *)
                commands;;
            esac
            
            注意事项:
                选项列表使用右半括号    )
                每个选项下的最一条命令后用两个分号作为结束    ;;
                Case结束之后使用esac结尾
        for命令
            for var in list
            do
            commands
            done
            注意事项:
                list参数:需要迭代的一系列值,
                在每次迭代时,var等于列表中的当前值
                最后一次迭代完成之后,var会保留最后的迭代值
        while命令
            while test command
            do
            other commands
            done
            意义:
                只要成立,就循环0
            注意事项:
                test command中可以有多个命令,但是只把最后一个命令的返回值作为判断条件
                Test command和if 命令中一模一样,不做解释
        until命令
            until test commands
            do
            other commands
            done
            意义:
                只要成立,就停止,否则就循环
    5. 函数
        创建
            function    func1 {
            commands
            }
            
            func2() {
            commands
            }
            和C语言的函数一样,使用函数需在定义函数后
            同名函数会覆盖之前的定义,没有报错
        运行
            bash shell会把函数当做小型脚本执行,运行结束之后会返回一个退出状态码
        函数退出
            退出状态码有三种生成方式
                默认退出状态码
                    函数中最后一条命令返回的退出状态码
                    使用特殊变量$? 获取
                使用return命令
                直接获取函数的输出
        函数入参
            函数传入参数的方法和给shell脚本传入参数的方法是一样的
            作为入参的特殊变量是局部的,只在函数内部起作用。
            shift命令会根据它们的相对位置来移动命令行参数,移出的参数值被丢弃
                当你不知道到底有多少参数时,可以使用shift命令,只需操作第一个参数
                $0 不会被移动。
高级编程
    shell父子关系
        我们在登录某个linux终端时,默认是以命令行的形式,这个命令行就是一个shell提供的CLI提示符
            我们在CLI提示符后输入的命令,都是由当前shell去执行。
        那么,如果我们再输入一个bash命令,或者其他的shell命令,会怎么样呢?
            其实bash命令已经重新创建了一个shell,我们需要借助ps命令查看。
            我们称新建立的shell为子shell,原来的shell为父shell。
        子shell仍然可以继续建立子shell。
        需要注意的是
            生成子shell的成本不低,速度还很慢,子子孙孙的嵌套更是很占用资源。
            在生成子shell时,只有部分父进程环境被复制到子shell环境中。
            其他诸如协程、进程列表相关内容,请自行学习。
    脚本控制-信号
        进程的信号就是预定义好的一个消息,进程能识别它并决定忽略还是作出反应。
        Linux利用信号与运行在系统中的进程进行通信,包括停止、启动、终止进程等等。
        有哪些信号:
            信号    值            描述                            简单描述
            1        SIGHUP        挂起进程                        
            2        SIGINT        终止进程                        Ctrl + C
            3        SIGQUIT        停止进程
            9        SIGKILL        无条件终止进程
            15        SIGTERM        尽可能终止进程
            17        SIGSTOP        无条件停止进程,但不是终止
            18        SIGTSTP        停止或暂停进程,但不终止        Ctrl + Z
            19        SIGCONT        继续运行停止的进程
        Ctrl + Z暂停进程后恢复的方法
            jobs 查看当前暂停的进程
            bg %N     将第N个进程恢复到后台
            fg  %N     将第N个进程恢复到前台
        其他信号:
            Ctrl + S : 锁定屏幕
            Ctrl + Q : 恢复显示
        信号捕获        我们可以主动捕获到上述信号并执行其他的命令
            Trap命令:
                启动捕获 :     Trap commands signals
                移除捕获 :    Trap --(-) signals
    有助于脚本调试的方法
        -n         不要执行脚本,仅检查语法错误
        -v        在执行脚本前,先将脚本内容输出到屏幕上。
        -x        将执行到的脚本语句,输出到屏幕上。
其他常用方法
    在脚本中读入文件
        有时,在脚本中使用管道等处理大量文件时不够方便
        我们可以将要处理的数据存入文件中,然后一行一行的读出来处理。
        本质:while 和 read 命令的高级使用方法。
            while read line
            do
                echo $line
            done < "./file"
        重要的原则
            重定向,必须在尾部
            对循环重定向的输出,可适用于循环中所有需要向标准输出写数据的命令。
            对循环重定向的输入,可适用于循环中所有需要从标准输入读数据的命令。
            当在循环内部显式的使用重定向时,内部重定向覆盖外部重定向。
    创建选单
        本质:    select 与 case 的配合使用
        Select :     向用户提供选项,供用户选择。将选择结果        的字符串存入变量中。
        PS3 :     使用select时的提示符
            PS3="Enter option: "
            select option in "one" "exit" ;
            do
                case $option in
                    "one")
                            echo -e "\nselect one\n"
                            ;;
                    "exit")
                            break
                            ;;
                esac
            done
    脚本参数补全
        原理
            Compgen –W        - 从选单中匹配候选单词列表
                complete        - 说明命令如何进行补全
                -F        指定执行函数名 , 候选结果保存在COMPREPLY变量中
                -f        补全文件名
                -X        过滤表达式
                -o        补全类型(filenames, dirnames)
        示例
            complete -o default -F _test_tab_func test.sh

            _test_tab_func()   
            {
                local cur prev opts
                
                COMPREPLY=()
                    
                cur="${COMP_WORDS[COMP_CWORD]}"  
                prev="${COMP_WORDS[COMP_CWORD-1]}"  
                opts="-help -usage -version -vvv "                  
                        
                if [[ ${cur} == * ]];then
                    COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
                    return 0
                fi  
            }
        生效方法
            将刚才编写的代码,加入~/.bashrc 等(不推荐)
            将上述代码,写入/etc/bash_completion.d/下,与命令名相同的脚本中。

            













                
    
    
   

posted on 2021-04-30 09:58  DavidPP  阅读(58)  评论(0编辑  收藏  举报