当前位置 博文首页 > ld95427的博客:shell编程汇总+awk+sed+grep

    ld95427的博客:shell编程汇总+awk+sed+grep

    作者:[db:作者] 时间:2021-09-12 18:15

    shell 编程


    变量

    定义变量

    • 变量名与变量内容以一个=连接,且等号两边不能有空格

    • 变量名称只能是英文字母、数字与下划线,但是不能以数字开头

    • 变量内容若有空格可使用双引号 " 或单引号' 将变量内容组合起来

      • 单引号' 为强引用,会将引号内的内容原样显示出来
      • 双引号 "为弱引用,会保持引号内特殊符号的原有特性
      song=1
      # 双引号保持特殊符号的原有特性
      s1="i am $song"
      echo $s1
      >i am 1
      
      # 单引号会将引号内的内容原样显示出来
      s2='i am $song'
      echo $s2
      >i am $song
      
    • 可用转意符 \ 将特殊符号(如 [Enter], $, \, 空格符, 等)变成一般字符

    • 在一串命令中,还需要藉由其他的命令提供的信息,可以使用以下两种方式

      # `命令`
      echo `ip a`
      # $(命令)  推荐
      echo $(ip a)
      
    • 增加变量的内容时,则可用以下两种方式

      song=1
      song=${song}55
      echo $song
      >155
      
    • 若该变量需要在其他子程序执行,则需要以 export 来使变量变成环境变量export song

      • 使自定义的变量 成为 环境变量,环境变量可以被向下继承(子进程 仅会继承父 shell 的环境变量, 不会继承父 shell 的自定义变量),并且 export 声明的环境变量只能被其子 shell 继承使用,不能被 父 shell 继承使用
      #例子
      [root@kube-master py3]# bash           # 打开一个子 shell
      [root@kube-master py3]# export a=hello # 在 子 shell 声明一个环境变量
      [root@kube-master py3]# bash           # 在子 shell 中再打开一个 子 shell
      [root@kube-master py3]# echo $a        # 变量可以生效
      hello
      [root@kube-master py3]# exit           # 退出 子 shell 的 子 shell
      exit
      [root@kube-master py3]# exit           # 退出 子 shell
      exit
      [root@kube-master py3]# echo $a        # 在 当前 shell 中, 其子 shell 声明的环境变量是无效的
      
      [root@kube-master py3]# 
      
    • 通常大写字符为系统默认变量,自定义变量可以使用小写字符,方便判断 (纯粹个人习惯) ;

    • 取消变量的方法为使用unset 变量名称 unset song

    环境变量

    这种变量是会影响bash环境操作的,会在真正进入系统前由一个bash程序读入到系统中。通常都环境变量的名字以大写字符命名。

    1、常见的环境变量

    • PATH 系统命令存放目录

    • HOME 当前用户的家目录

    • MAIL

    • SHELL

    • PWD 当前所在目录

    • USER 当前用户

    • UID 当前用户的uid

    • ID 当前用户的组id

    • RANDOM 随机数

    • PS1 提示字符

      可用的提示字符的含义

      • \d :可显示出“星期 月 日”的日期格式,如:“Mon Feb 2”
      • \H :完整的主机名称。如 www.sharkyun.com
      • \h :仅取主机名称在第一个小数点之前的名字, www
      • \t :显示时间,为 24 小时格式的“HH:MM:SS”
      • \T :显示时间,为 12 小时格式的“HH:MM:SS”
      • \A :显示时间,为 24 小时格式的“HH:MM”
      • \@ :显示时间,为 12 小时格式的“am/pm”样式
      • \u :目前使用者的帐号名称,如“dmtsai”;
      • \v :BASH 的版本信息
      • \w :完整的工作目录名称,由根目录写起的目录名称。但主文件夹会以 ~ 取代;
      • \W :利用 basename 函数取得工作目录名称,所以仅会列出最后一个目录名。
      • \# :下达的第几个指令。
      • \$ :提示字符,如果是 root 时,提示字符为 # ,否则就是 $

      颜色表

      前景 背景 颜色

      30 40 黑色

      31 41 红色

      32 42 绿色

      33 43 黄色

      34 44 蓝色

      35 45 紫红色

      36 46 青蓝色

      37 47 白色

      代码 意义

      0 OFF

      1 高亮显示

      4 underline

      7 反白显示

      8 不可见

      设置PS1

      设置颜色 [\e[F;Bm\] 其中“F”为字体颜色,编号30~37;“B”为背景色,编号40~47

      取消设置 [\e[m\] 如果不取消 后面的所有内容都会是这个颜色

      # 可以显示git状态的
      function parse_git_dirty {
      [[ $(git status 2> /dev/null | tail -n1) != "nothing to commit (working directory clean)" ]] && echo "*"
      }
      function parse_git_branch {
      git branch --no-color 2> /dev/null | sed -e '/^[^*]/d' -e "s/* \(.*\)/git:\1$(parse_git_dirty)/"
      }
      export PS1="\[\e[36m\]○\[\e[33m\]\$(parse_git_branch)\[\e[m\] {\[\e[36m\]>\#< \[\e[34m\]\u@\h \e[33m\]\[\e[m\]}\n \[\e[31m\]\w○\$ →\[\e[m\]"
      

    2、列出shell环境下的所有环境变量及其内容

    • env 是 environment (环境) 的简写,所有的环境变量(包含自定义的环境表里)
    • set 列出系统中所有的变量,包括自定义的变量

    3、bash 的环境变量文件

    • longin shell
      取得shell时需要完整的登入流程;特点是登入时需要用户帐号和密码
    • no-login shell
      取得shell时不需要再次输入帐号和密码的情况下,所得到的 shell

    longin shell 会读取以下两个文件:

    1. ·/etc/profile· :这是系统整体设定,最好不要修改
    2. ·~/.bash_profile~/.bash_login~/.profile` :属于个人的配置文件

    /etc/profile 会主动依序调用以下脚本文件:

    • /etc/inputrc :定义快捷键
    • /etc/profile.d/*sh :定义bash操作接口颜色、语系、命令别名等
    • etc/locale.conf :定义系统的默认语系

    bash 在读完 /etc/profile 后,接下来会读取以下3个文件,且只会读去一个,会按照以下顺序优先读取

    ~/.bash_profile  //会调用 ~/.bashrc,也会有新的环境变量在下面的文件中被添加
    ~/.bash_login
    ~/.profile
    

    最终,~/.bashrc 才是最后被读入到系统环境中的文件

    让这些环境变量文件中的变量等设置及时在当前 shell 终端中生效,有下两种方式

    source ~/.bashrc 
    或者
    . ~/.bashrc
    no-longin shell  当取得no-longin shell时,该shell仅会读取 ~/.bashrc 文件 而~/.bashrc最后又会调用 /etc/bashrc
    

    /etc/bashrc 的作用:

    ? 依据不同的UID定义出 umask
    ? 依据不同的UID定义出提示符(就是PS1变量)
    ? 呼叫 /etc/profile.d/*.sh 的设定

    其他的相关配置文件

    ? /etc/man.config
    这个文件最重要的就是定义了MANPATH 这个变量,它定义了man page 的路径;在以tarball的方式安装软件时有用
    ? ~/.bash_history
    历史命令记录文件;记录的数量与HISTFILESIZE变量有关。在/etc/profile
    ? ~/.bash_logout
    记录了当我注销bash后,系统再帮我做完什么动作后才离开的。

    4、预定义变量

    预定义的特殊变量有着特殊的含义,用户不可以更改,所有的预定义变量都由 $ 符号和另外一个符号组成

    # 常用的预定义特殊变量如下
    $$ 当前进程PID
    $? 命令执行后的返回状态.0 为执行正确,非 0 为执行错误 
    $# 位置参数的数量
    $* 所有位置参数的内容   
    $@ 显示所有的参数
    $! 上一个后台进程的PID (wait命令中使用,后面讲)
    

    5、从键盘的输入给变量赋值 read

    read [-pt] 变量名
    选项参数:
    -p :后面可以接提示字符!
    -t :后面可以接等待的『秒数!』,比如 -t 5 提示用户输入信息时间是 5 秒钟,超过 5 秒钟,程序就继续向下运行
    
    例子:
    read -p “请输入你的姓名” name
    
    echo "你的姓名是: $name"
    

    6、变量的删除、取代和替换

    • 删除

      • 从后往前删除${变量%匹配的内容}
      • 从前往后删除${变量#匹配的内容}
    • 替换(就是设置默认值)
      在这里插入图片描述

      最常用的是var=${str:-expr} 后面的expr就是设置的默认值

    7、时间变量的计算

    // 计算 3 小时之后是几点几分
    date +%T -d '3 hours'
    
    // 任意日期的前 N 天,后 N 天的具体日期
    date +%F -d "20190910 1 day"
    date +%F -d "20190910 -1 day"
    
    // 计算两个日期相差天数, 比如计算生日距离现在还有多少天
    d1=$(date +%s -d 20180728)
    d2=$(date +%s -d 20180726)
    echo $((   (d1-d2)     /   86400          ))
    
    # 输出 
    2
    

    8、位置变量

    位置变量也属于预定义的变量
    位置变量针对于脚本来说
    位置变量是根据命令出现在命令行上的位置来确定的变量,在shell调用过程中,会按参数所在的位置进行调用。

    假如脚本中使用了一个位置变量,但是执行脚本的时候,传入了多个参数,程序并不会报错。但是执行的时候只传入了一个参数,同样不会报错,后面的位置参数不会被赋值

    脚本基础

    脚本的执行方式

    • source 脚本 在父进程中执行脚本代码
    • sh 脚本 在子进程中执行脚本代码,相当于打开了一个子shell,一个全新的环境
    • ./脚本

    set

    • set -u

      • 当脚本中遇到未定义的变量时,默认是忽略。有时候这并不是开发者想要的。假如有未定义的变量,应该报错,并且终止脚本继续运行。
        在这里插入图片描述
    • set -e

    • 在脚本执行中,有任何命令的返回值是非 0 的情况,则正在运行的脚本则会退出。对于一组含有管道的命令无效。

      # 设置之前
      [root@kube-master set]# cat set-e-before.sh
      #!/bin/sh
      
      foo
      echo "继续执行"
      [root@kube-master set]# sh set-e-before.sh
      set-e-before.sh: line 3: foo: command not found
      继续执行
      
      # 设置之后
      [root@kube-master set]# cat set-e-after.sh
      #!/bin/sh
      
      set -e
      
      foo
      echo "继续执行"
      [root@kube-master set]# sh set-e-after.sh
      set-e-after.sh: line 5: foo: command not found
      
      # 对于含有管道的命令无效
      #!/usr/bin/env bash
      set -e
      foo | echo "shark"    # 注意这里有管道符
      echo  "程序会继续运行"
      [root@kube-master set]# sh set-e.sh
      shark
      set-e.sh: line 2: foo: command not found   # 这是报错信息
      程序会继续运行
      
      # foo 不是 shell 中的命令,执行会报错,但是其后面有个管道,最终管道后的 echo 命令执行成功了,这种情况下 脚本会继续执行。
      
    • set -o pipefail

      • 需要和 set -e 配合使用。如果设置,如果管道中的所有命令都成功退出,整条命令的返回值才是 0。否则返回非 0
        默认情况下禁用此选项
      # 设置 set -o pipefail 后,此时脚本就会终止运行
      set -e
      set -o pipefail
      foo |echo ''
      echo shark
      [root@kube-master set]# sh set-e-pipefail.sh
      
      set-e-pipefail.sh: line 4: foo: command not found
      

    基础语法

    判断

    • test

      测试的标制代表的意义
      判断是否存在
      例子 test -e filename
      -e该文件名是否存在
      -f该文件名是否存在且为文件
      -d该文件名是否存在且为目录
      检测文件权限
      例子 test -r filename
      -r检测该文件名是否存在且可读
      -w检测该文件名是否存在且可写
      -x检测该文件名是否存在且可执行
      -u检测该文件名是否存在且具有suid属性
      -g检测该文件名是否存在且具有sgid属性
      -k检测该文件名是否存在且具有sticky bit属性
      -s检测该文件名是否存在且为非空白文件
      两文件比较
      例子 test file1 -nt file2
      -nt判断文件1是否比文件2新
      -ot判断文件1是否比文件2旧
      -ef判断文件1与文件2是否为同一文件(inode号是否一致),可用在判断硬链接上
      两个整数之间的判断
      例子 test n1 -eq n2
      -eq相等
      -ne不等
      -gt大于
      -lt小于
      -ge大于等于
      -le小于等于
      字符串及变量判断
      test -z string判断长度是否为0,若string 为空字串,返回true
      test string
      test !-z string
      判断长度是否为0,若string 为空字串,返回falseww’w
      test str1 == str2判断str1是否等于str2,相等则返回true
      test str1 != str2判断str1是否不等于str2,相等则返回false
      在shell中以下两种情况,变量的长度均视为0
      1、变量未定义
      2、变量定义了,但赋值为空字符串,如a=''
      多重条件判断
      例如:test -r filename -a -x filename
      -a和 两个条件同时成立
      -o或 两个条件有任意一个成立
      !取反
    • 判断符号[ ]

      • 在中括号中的每个元素之间都需要用空格来分隔
      • 在中括号内的变量最好都用双引号括起来
      • 可以跟的选项与test一致,例如[ -f filename]
      # 错误示范
      # 定义变量
      name="shark ops"
      
      # 开始测试值是否相等
      [ ${name} == "xiguatian" ]
      
      # 报错
      bash: [: too many arguments
      
      # 正确的写法
      [ "${name}" == "xiguatian" ]
      

    逻辑语句

    1、if判断

    # 单层
    if [ 判断条件 ];then
      条件成立时执行的语句
    fi
    
    # 含有else的单层结构
    if [ 判断条件 ];then
      条件成立时执行的语句
    else
      条件不成立时执行的语句
    fi
    
    # 多条件判断,elif可以有多个
    if [ 判断条件1 ];then
      条件1成立时执行的语句
    elif [ 判断条件2 ];then
      条件2成立时执行的语句
    else
      条件都不成立时执行的语句
    fi
    
    # 如果在判断中使用正则,则要将条件用 [[ ]] 括起来,使用 =~ 来进行匹配,如果不想匹配 则使用[[ ! 条件 ]]
    #例子
    #!/usr/bin/env   sh
    name=shark
    # 匹配
    if [[ "$name"  =~  [a-z]+ ]];then
       echo "ok"
    fi
    # 不匹配
    if [[ ! "$name" =~ [0-9]+ ]];then
       echo  "good"
    fi
    
    # 嵌套,在一个 if 判断中还可以嵌套多个if判断或其他语句,只要结构完整就好
    

    2、case语句

    # 基本语法
    case  $变量名称 in       <==关键字为 case ,还有变量前有钱字号
      "第一个变量的值")       <==每个变量内容建议用双引号括起来,关键字则为小括号 )
        程序段
        ;;                  <==每个类别结尾使用两个连续的分号来处理!
      "第二个变量的值")
        程序段
        ;;
      *)                    <==最后一个变量内容都会用 * 来代表所有其他值
        不包含第一个变量内容与第二个变量内容的其他程序运行段
        exit 1
        ;;
    esac                    <==反过来写,结束当前语句结构!
    
    # 例子,变量值不仅可以是一个,也可以是多个
    #!/bin/bash
    cat << EOF
    m|M) show memory usages;
    d|D) show disk usages;
    q|Q) quit
    EOF
    read -p "Your choice" choice
    case $choice in
    m|M)
            free -m
            ;;
    d|D)
            df -h
            ;;
    q|Q)
            exit
            ;;
    *)
            eco "Invalid input"
            ;;
    esac
    

    3、while语句

    # 基础语句
    while [ condition ]  ==>中括号内的状态就是判断式
    do                   ==> do 是循环的开始!
        命令或者代码
        命令或者其他逻辑语句
    done                 ==> done 是循环的结束
    
    #每次循环体执行完,while 都会检查条件是否为真,为真继续循环,否则终止循环
    #所以在使用while循环时,如果不想进入无限循环,按情况添加条件
    
    
    # read
    # read可以同时添加多个变量
    [root@sharkyun ~]# read id name age
    1 shark 18
    [root@sharkyun ~]# echo $age
    18
    [root@sharkyun ~]# echo $id  $name
    1 shark
    # read默认分割符为空格,可以修改,IFS就是存储分割符的
    [root@sharkyun ~]# old_ifs=$IFS; IFS=','
    [root@sharkyun ~]# read id name age
    2, xiguatian, 20
    [
    
    下一篇:没有了