• 【Linux】【Shell】【Basic】Programming


    shell脚本编程:

      编程语言的分类:根据运行方式

        编译运行:源代码--》编译器(编译)--》程序文件

        解释运行:源代码--》运行时启动解释器,又解释器边解释边运行

      根据其编程过程中功能的实现是调用库还是调用外部的程序文件:、

        shell脚本编程:
          利用系统上的命令及编程组件进行编程;
        完整编程:
          利用库或编程组件进行编程;

      编程模型:过程式编程语言,面向对象的编程语言
        程序=指令+数据
          过程式:以指令为中心来组织代码,数据是服务于代码;
            顺序执行
            选择执行
            循环执行
            代表:C,bash
          对象式:以数据为中心来组织代码,围绕数据来组织指令;
            类(class):实例化对象,method;
            代表:Java, C++, Python

      shell脚本编程:过程式编程,解释运行,依赖于外部程序文件运行;

        如何写shell脚本:
          脚本文件的第一行,顶格:给出shebang,解释器路径,用于指明解释执行当前脚本的解释器程序文件
            常见的解释器:
              #!/bin/bash
              #!/usr/bin/python
              #!/usr/bin/perl

        文本编程器:nano
          行编辑器:sed
          全屏幕编程器:nano, vi, vim

        shell脚本是什么?
          命令的堆积;
          但很多命令不具有幂等性,需要用程序逻辑来判断运行条件是否满足,以避免其运行中发生错误;

        运行脚本:
          (1) 赋予执行权限,并直接运行此程序文件;
            chmod +x /PATH/TO/SCRIPT_FILE
            /PATH/TO/SCRIPT_FILE
          (2) 直接运行解释器,将脚本以命令行参数传递给解释器程序;
            bash /PATH/TO/SCRIPT_FILE

        注意:脚本中的空白行会被解释器忽略;
           脚本中,除了shebang,余下所有以#开头的行,都会被视作注释行而被忽略;此即为注释行;
           shell脚本的运行是通过运行一个子shell进程实现的;

    练习1:写一个脚本,实现如下功能;
    (1) 显示/etc目录下所有以大写p或小写p开头的文件或目录本身;
    (2) 显示/var目录下的所有文件或目录本身,并将显示结果中的小写字母转换为大写后显示;
    (3) 创建临时文件/tmp/myfile.XXXX;

      bash的配置文件:
        两类:
          profile类:为交互式登录的shell进程提供配置

            全局:对所有用户都生效;
              /etc/profile 
              /etc/profile.d/*.sh

            用户个人:仅对当前用户有效;
              ~/.bash_profile

            功用:
              1、用于定义环境变量;
              2、运行命令或脚本;
          bashrc类:为非交互式登录的shell进程提供配置

            全局:
              /etc/bashrc 
            用户个人:
              ~/.bashrc

            功用:
              1、定义本地变量;
              2、定义命令别名;

            注意:仅管理员可修改全局配置文件;

        登录类型:
          交互式登录shell进程:
            直接通过某终端输入账号和密码后登录打开的shell进程;
            使用su命令:su - USERNAME, 或者使用 su -l USERNAME执行的登录切换;
            /etc/profile --> /etc/profile.d/* --> ~/.bash_profile --> ~/.bashrc --> /etc/bashrc


          非交互式登录shell进程:
            su USERNAME执行的登录切换;
            图形界面下打开的终端;

            ~/.bashrc --> /etc/bashrc --> /etc/profile.d/*
            运行脚本


          命令行中定义的特性,例如变量和别名作用域为当前shell进程的生命周期;
          配置文件定义的特性,只对随后新启动的shell进程有效;

          让通过配置文件定义的特性立即生效:
            (1) 通过命令行重复定义一次;
            (2) 让shell进程重读配置文件;
              ~]# source /PATH/FROM/CONF_FILE
              ~]# . /PATH/FROM/CONF_FILE

    bash脚本编程
     
        脚本文件格式:
            第一行,顶格:#!/bin/bash
            注释信息:#
            代码注释:
            缩进,适度添加空白行;
             
        语言:编程语法格式,库,算法和数据结构
        编程思想:
            问题空间 --> 解空间
             
        变量:
            局部变量
            本地变量
            环境变量
             
            位置参数变量
            特殊变量
             
        数据类型:字符型、数值型
            弱类型:字符型
             
        算术运算:
            +, -, *, /, %, **
             
            let  VAR=expression
            VAR=$[expression]
            VAR=$((expression))
            VAR=$(expr argu1 argu2 argu3)
             
            注意:有些时候乘法符号需要转义;
             
            增强型赋值:
                变量做某种算术运算后回存至此变量中;
                    let i=$i+#
                    let i+=#
                     
                +=,-=,*=, /=, %=
                 
                自增:
                    VAR=$[$VAR+1]
                    let  VAR+=1
                    let  VAR++
                     
                自减:
                    VAR=$[$VAR-1]
                    let  VAR-=1
                    let  VAR--
                     
        练习:
            1、写一个脚本
                计算/etc/passwd文件中的第10个用户和第20个用户的id号之和;
                    id1=$(head -10  /etc/passwd | tail -1  | cut  -d:  -f3)
                    id2=$(head -20   /etc/passwd | tail -1  | cut  -d:  -f3)
                     
                 
            2、写一个脚本
                计算/etc/rc.d/init.d/functions和/etc/inittab文件的空白行数之和;
                 
                    grep "^[[:space:]]*$"   /etc/rc.d/init.d/functions | wc -l
                     
        条件测试:
            判断某需求是否满足,需要由测试机制来实现;
             
            如何编写测试表达式以实现所需的测试:
                (1) 执行命令,并利用命令状态返回值来判断;
                    0:成功
                    1-255:失败
                (2) 测试表达式
                    test  EXPRESSION
                    [ EXPRESSION ]
                    [[ EXPRESSION ]]
                     
                    注意:EXPRESSION两端必须有空白字符,否则为语法错误;
                     
            bash的测试类型:
                数值测试
                字符串测试
                文件测试
                 
                数值测试:数值比较
                    -eq:是否等于; [ $num1 -eq $num2 ]
                    -ne:是否不等于;
                    -gt:是否大于;
                    -ge:是否大于等于;
                    -lt:是否小于;
                    -le:是否小于等于;
                     
                字符串测试:
                    ==:是否等于;
                    >:是否大于;
                    <:是否小于;
                    !=:是否不等于;
                    =~:左侧字符串是否能够被右侧的PATTERN所匹配;
                     
                    -z "STRING":判断指定的字串是否为空;空则为真,不空则假;
                    -n "STRING":判断指定的字符串是否不空;不空则真,空则为假;
                     
                    注意:
                        (1) 字符串要加引用;
                        (2) 要使用[[ ]];
                         
                文件测试:
                    存在性测试
                        -a  FILE
                        -e  FILE
                            文件的存在性测试,存在则为真,否则则为假;
                    存在性及类型测试
                        -b  FILE:是否存在并且为 块设备 文件;
                        -c  FILE:是否存在并且为 字符设备 文件;
                        -d  FILE:是否存在并且为 目录文件;
                        -f  FILE:是否存在并且为 普通文件;
                        -h  FILE或 -L  FILE:是否存在并且为 符号链接文件;
                        -p FILE:是否存在且为 命名管道文件;
                        -S  FILE:是否存在且为 套接字文件;
                    文件权限测试:
                        -r  FILE:是否存在并且 对当前用户可读;
                        -w  FILE:是否存在并且 对当前用户可写;
                        -x  FILE:是否存在并且 对当前用户可执行;
                    特殊权限测试:
                        -u  FILE:是否存在并且 拥有suid权限;
                        -g  FILE:是否存在并且 拥有sgid权限;
                        -k  FILE:是否存在并且 拥有sticky权限;
                    文件是否有内容:
                        -s  FILE:是否有内容;
                    时间戳:
                        -N FILE:文件自从上一次读操作后是否被修改过;
                    从属关系测试:
                        -O  FILE:当前用户是否为文件的属主;
                        -G  FILE:当前用户是否属于文件的属组;
                    双目测试:
                        FILE1  -ef  FILE2:FILE1与FILE2是否指向同一个文件系统的相同inode的硬链接;
                        FILE1  -nt  FILE2:FILE1是否新于FILE2;
                        FILE1  -ot  FILE2:FILE1是否旧于FILE2;
                         
                组合测试条件:
                    逻辑运算:
                        第一种方式:
                            COMMAND1 && COMMAND2
                            COMMAND1 || COMMAND2
                            ! COMMAND
                             
                            [ -O FILE ] && [ -r FILE ]
                             
                        第二种方式:
                            EXPRESSION1  -a  EXPRESSION2
                            EXPRESSION1  -o  EXPRESSION2
                            ! EXPRESSION
                             
                            [ -O FILE -a -x FILE ]
                             
                    练习:将当前主机名称保存至hostName变量中;
                        主机名如果为空,或者为localhost.localdomain,则将其设置为www.magedu.com;
                         
                        hostName=$(hostname)
                         
                        [ -z "$hostName" -o "$hostName" == "localhost.localdomain" -o "$hostName" == "localhost" ] && hostname www.magedu.com                  
                         
            脚本的状态返回值:
                默认是脚本中执行的最后一条件命令的状态返回值;
                自定义状态退出状态码:
                    exit  [n]:n为自己指定的状态码;
                        注意:shell进程遇到exit时,即会终止,因此,整个脚本执行即为结束;
                         
        向脚本传递参数:
            位置参数变量
             
            myscript.sh  argu1 argu2
                引用方式:
                    $1,  $2, ..., ${10}, ${11}, ...
                     
                轮替:
                    shift  [n]:位置参数轮替;
                     
            练习:写一脚本,通过命令传递两个文本文件路径给脚本,计算其空白行数之和;
                 
                #!/bin/bash
                #
                file1_lines=$(grep "^$" $1 | wc -l)
                file2_lines=$(grep "^$" $2 | wc -l)
     
                echo "Total blank lines: $[$file1_lines+$file2_lines]" 
                 
        特殊变量:
            $0:脚本文件路径本身;
            $#:脚本参数的个数;
            $*:所有参数
            $@:所有参数
     
        过程式编程语言的代码执行顺序:
            顺序执行:逐条运行;
            选择执行:
                代码有一个分支:条件满足时才会执行;
                两个或以上的分支:只会执行其中一个满足条件的分支;
            循环执行:
                代码片断(循环体)要执行0、1或多个来回;
                 
            选择执行:
                单分支的if语句:
                    if  测试条件
                    then
                        代码分支
                    fi
                 
                双分支的if语句:
                    if  测试条件; then
                        条件为真时执行的分支
                    else
                        条件为假时执行的分支
                    fi
                     
            示例:通过参数传递一个用户名给脚本,此用户不存时,则添加之;
                #!/bin/bash
                #
                if ! grep "^$1>" /etc/passwd &> /dev/null; then
                    useradd $1
                    echo $1 | passwd --stdin $1 &> /dev/null
                    echo "Add user $1 finished."
                fi 
                 
                #!/bin/bash
                #
                if [ $# -lt 1 ]; then
                    echo "At least one username."
                    exit 2
                fi
     
                if ! grep "^$1>" /etc/passwd &> /dev/null; then
                    useradd $1
                    echo $1 | passwd --stdin $1 &> /dev/null
                    echo "Add user $1 finished."
                fi     
                     
                #!/bin/bash
                #
                if [ $# -lt 1 ]; then
                    echo "At least one username."
                    exit 2
                fi
     
                if grep "^$1>" /etc/passwd &> /dev/null; then
                    echo "User $1 exists."
                else
                    useradd $1
                    echo $1 | passwd --stdin $1 &> /dev/null
                    echo "Add user $1 finished."
                fi         
                 
            练习1:通过命令行参数给定两个数字,输出其中较大的数值;
                #!/bin/bash
                #
                if [ $# -lt 2 ]; then
                    echo "Two integers."
                    exit 2
                fi
     
                if [ $1 -ge $2 ]; then
                    echo "Max number: $1."
                else
                    echo "Max number: $2."
                fi
     
                 
                #!/bin/bash
                #
     
                if [ $# -lt 2 ]; then
                    echo "Two integers."
                    exit 2
                fi
     
                declare -i max=$1
     
                if [ $1 -lt $2 ]; then
                    max=$2
                fi
     
                echo "Max number: $max."
                         
            练习2:通过命令行参数给定一个用户名,判断其ID号是偶数还是奇数;
            练习3:通过命令行参数给定两个文本文件名,如果某文件不存在,则结束脚本执行;
                都存在时返回每个文件的行数,并说明其中行数较多的文件;
             
             
        练习:
            1、创建一个20G的文件系统,块大小为2048,文件系统ext4,卷标为TEST,要求此分区开机后自动挂载至/testing目录,且默认有acl挂载选项;
                (1) 创建20G分区;
                (2) 格式化:
                    mke2fs -t ext4 -b 2048 -L 'TEST' /dev/DEVICE
                (3) 编辑/etc/fstab文件
                LABEL='TEST'    /testing    ext4    defaults,acl    0 0
     
            2、创建一个5G的文件系统,卷标HUGE,要求此分区开机自动挂载至/mogdata目录,文件系统类型为ext3;
     
            3、写一个脚本,完成如下功能:
                (1) 列出当前系统识别到的所有磁盘设备;
                (2) 如磁盘数量为1,则显示其空间使用信息;
                    否则,则显示最后一个磁盘上的空间使用信息;
                    if [ $disks -eq 1 ]; then
                        fdisk -l /dev/[hs]da
                    else
                        fdisk -l $(fdisk -l /dev/[sh]d[a-z] | grep -o "^Disk /dev/[sh]d[a-]" | tail -1 | cut -d' ' -f2)
                    fi
     
     
    bash脚本编程之用户交互:
        read [option]... [name ...]
            -p 'PROMPT'
            -t TIMEOUT
     
        bash -n /path/to/some_script
            检测脚本中的语法错误
     
        bash -x /path/to/some_script
            调试执行
     
        示例:
            #!/bin/bash
            # Version: 0.0.1
            # Author: MageEdu
            # Description: read testing
     
            read -p "Enter a disk special file: " diskfile
            [ -z "$diskfile" ] && echo "Fool" && exit 1
     
            if fdisk -l | grep "^Disk $diskfile" &> /dev/null; then
                fdisk -l $diskfile
            else
                echo "Wrong disk special file."
                exit 2
            fi
  • 相关阅读:
    UVA
    codeforces #371div2 B
    POJ-3278 Catch That Cow
    巴士博弈
    权势二进制
    HDU
    SQL 函数
    SQL 查询语句×45
    SQL 触发器
    SQL 连接查询
  • 原文地址:https://www.cnblogs.com/demonzk/p/6278594.html
Copyright © 2020-2023  润新知