zoukankan      html  css  js  c++  java
  • SHELL

    Shell脚本编程

    1.shell程序编程风格

    面向过程语言

    多一件事,排出个步骤,第一步干什么,第二步干什么,如果出现情况A,做什么处理,如果出现了情况B,做什么处理

    问题规模小,可以步骤化,按部就班处理

    以指令为中心,数据服务于指令

    2.脚本创建过程

    第一步:使用文本编辑器来创建文本文件

    第一行必须包括shell声明序列: #!

    #!/bin/bash

    添加注释,注释以#开头

    第二步:加执行权限

    给予执行权限,在命令行上指定脚本的绝对或相对路径

    第三步:运行脚本

    直接运行解释器,将脚本作为解释器程序的参数运行

    3.第一个脚本hello world

    [21:25:28 root@aiyoubucuo ~]$cat /data/ybw.sh 
    #!/bin/bash
    echo "hello world"

     [21:28:30 root@aiyoubucuo ~]$. /data/ybw.sh
      hello world

    4.shell脚本调试

    只检测脚本中语法错误,但无法检查出命令错误,但不真正执行脚本

    bash -n /data/ybw.sh

    调试并执行

    bash -x /data/ybw.sh

    5.Shell变量类型

    内置变量,如:PS1,PATH,UID,HOSTNAME,BASHPID

    用户自定义变量

    不同的变量存放的数据不同,决定了以下

    数据存储方式

    参与的运算

    表示的数据范围

    6.变量的使用变量

    使用一个定义过的变量,只要在变量名前面加美元符号即可

    your="ybw"
    echo $your
    echo ${your_name}

    #变量名外面的{花括号}是可选的,为了帮助解释器识别变量的边界

    7.只读变量

    使用 readonly 命令可以将变量定义为只读变量,只读变量的值不能被改变。

    下面的例子尝试更改只读变量,结果报错:

    #!/bin/bash
    your="jommy"
    readonly your
    your="zxx"

    运行脚本结果:

    [root@localhost ~]# ./2.sh 
    ./2.sh: line 4: your: readonly variable

    8.删除变量

    使用 unset 命令删除变量

    unset jommy

    变量被删除后不能再次使用。unset 命令不能删除只读变量。

    #!/bin/bash
    your="ybw"
    unset your
    echo $your

    以上运行没有任何输出结果

    9.位置变量

    位置变量:在bash shell中内置的变量,在脚本代码中调用通过命令行传递给脚本的参数

     $1,$2 ... 对应第1个,第2个等参数,shift【n】换位置

    $0 命令本身,包括路径

    $* 传递给脚本的所有参数,全部参数整合为一个字符串

    $@ 传递给脚本的所有参数,每个参数为独立字符串

    $# 传递给脚本的参数的个数

    echo "1st arg is $1"
    echo "2st arg is $2"
    echo "3st arg is $3"
    echo "10st arg is ${10}"
    echo "11st arg is ${11}"
    
    echo "the number of arg is $#"
    echo "all args are $*"
    echo "all args are $@"
    echo "the scriptime is `basename $0`"
    [13:33:22 root@aiyoubucuo ~]./arg.sh {a..z}
    1st arg is a
    2st arg is b
    3st arg is c
    10st arg is j
    11st arg is k
    the number of arg is 26
    all args are a b c d e f g h i j k l m n o p q r s t u v w x y z
    all args are a b c d e f g h i j k l m n o p q r s t u v w x y z
    the scriptime is arg.sh

     10.退出状态码变量

    $?的值为0 代表成功

    $?的值是1-255 代表失败

    [20:03:49 root@aiyoubucuo ~]curl http://www.baidu.com
    [20:04:02 root@aiyoubucuo ~]$?
    0: command not found
    访问百度结果是0
    [20:04:11 root@aiyoubucuo ~]curl http://www.sdhfuiashdncieow.com
    curl: (6) Could not resolve host: www.sdhfuiashdncieow.com
    [20:04:43 root@aiyoubucuo ~]$?
    6: command not found
    瞎输入一个结果是6

    用户可以在脚本中使用以下命令自定义退出状态码

    exit [n]

    脚本中一旦遇到exit命令,脚本会立即终止;终止退出状态取决于exit命令后面的数字

    如果为给脚本退出状态码,整个脚本的退出状态码取决于脚本中执行的最后一条命令的状态码

    11.脚本安全和set

    set命令可以来定制shell环境

    -u 在扩展一个没有设置的变量时,显示错误信息

    -e 如果一个命令返回一个非0退出状态值(失败)就退出

    可以一起使用set -eu,但输出结果显示错误就退出,有时候不是那种真正的错误也会退出

    12.格式化输出printf

    printf “指定的格式” 文本1 文本2

    %s:字符串

    %f:浮点格式

    常用转义字符

    :换行

    f:换页

    :后退

    [20:31:59 root@aiyoubucuo ~]printf "(%s)
    " 1 2 3
    (1)
    (2)
    (3)

    13.算数运算

    bash只支持整数,不支持小数

    var=$((算术表达式))

    var=$[算数表达式]

    $RANDOM 取值范围0-32767

     14.逻辑运算

    1,真

    2,假

    以上为二进制

    [20:50:37 root@aiyoubucuo ~]true
    [21:06:40 root@aiyoubucuo ~]echo $?
    0
    [21:06:49 root@aiyoubucuo ~]false
    [21:06:56 root@aiyoubucuo ~]echo $?
    1

    短路与

    CMD1 短路与 CMD2

    第一个CMD1结果为真,第二个CMD2必须要参与运算,才能得到最终结果

    第一个CMD1结果为假,总的结果必定为0,因此不需要执行CMD2

    也可以用&&表示短路与

    命令1成功执行命令2,否则不执行命令2

    短路或

    CMD1 短路或 CMD2

    第一个CMD1结果为真,总的结果必定为0,因此不需要执行CMD2

    第一个CMD1结果为假,第二个CMD2必须要参与运算,才能得到最终结果

    也可以用||表示短路或

    命令1成功将不执行命令2,否则将执行命令2

    &&和||组合使用

     如果有wang账户则执行echo命令,没有则执行创建用户命令

     15.条件测试命令

    若真,则状态码变量$?返回0

    若假,则状态码变量$?返回1

    test EXPRESSION

    [EXPRESSION]和test等价

    [[EXPRESSION]]用法

    =~ 左侧字符串是否能够被右侧的征兆表达式匹配,支持正则表达式

    [21:25:06 root@aiyoubucuo ~]#[[ $IP =~ ^(([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]
    |25[0-5]).){3}([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$ ]]

    [21:27:45 root@aiyoubucuo ~]#echo $?
    1
    判断ip是否合法

    16.数值测试

    -eq是否大于等于

    -ne是否不等于 

    -gt是否大于

    -ge是否大于等于

    -lt是否小于

    -le是否小于等于

    [21:18:16 root@aiyoubucuo ~]i=10
    [21:18:20 root@aiyoubucuo ~]j=8
    [21:18:28 root@aiyoubucuo ~][ $i -gt $j ]
    [21:19:09 root@aiyoubucuo ~]echo $?
    0

    17.关于()和{}

    两种符号都可以将多个命令组合在一起,批量执行

    (list)会开启子shell,并且list中变量赋值及内部命令执行后,将不再影响后续的环境

      {list} 不会开启子shell,在当前shell中运行,会影响当前shell环境

    [21:36:58 root@aiyoubucuo ~]name=ybw;(echo $name;name=yang;echo $name);echo $name
    ybw
    yang
    ybw
    [21:37:06 root@aiyoubucuo ~]name=ybw;{ echo $name;name=yang;echo $name; } ;echo $name
    ybw
    yang
    yang

    18.read

    使用read命令来接受输入

    使用read来把输入值分配给一个或多个shell变量,read从标准输入中读取值,给每一个单词分配一个变量,所有剩余单词被分配给最后一个变量,如果变量名没有指定,默认标准输入的值赋给系统内置变量reply

    read 选项 【name...】

    -p指定要显示的提示,常用

     19.if

    单分支

    if 判断条件;then

    条件为真的分支代码

    fi

    双分支

    f 判断条件;then

    条件为真的分支代码

    else

    条件为假的分支代码

    fi

    多分支

    if 判断条件1;then

     条件1为真的分支代码

    elif 判断条件2;then

    条件2为真的分支代码

    elif 判断条件3;then

    条件3为真的分支代码

    ...

    else

    以上条件都为假的分支代码

    fi

    例子

    #!/bin/bash
    read -p "请输入身高(m为单位):" HIGH
       if [[ ! "$HIGH" =~ ^[0-2](.[0-9]{,2})?$ ]];then
              echo "输入身高错误"
             exit 1
       fi
      read -p "请输入体重(kg为单位):" WEIGHT
       if [[ ! "$WEIGHT" =~ ^[0-9]{1,3}$ ]];then
              echo "输入体重错误"
             exit 1
       fi
    BMI=`echo $WEIGHT/$HIGH^2|bc`
    if [ $BMI -le 18 ] ;then
            echo "太瘦了宝贝,多吃点"
    elif [ $BMI -lt 24 ] ;then
            echo "身材不错,想办法追我"
    else
            echo "你是猪吗宝贝"
    fi

    19.条件判断case语句

    case支持通配符

    #!/bin/bash
    echo "1,备份数据库"
    echo "2.清理日志"
    echo "3.软件升级"
    echo "4.软件回滚"
    read -p "请选择上面数字1-4:" MENU case $MENU in 1) echo "备份数据" ;; 2) echo "清理日志" ;; 3) echo "软件升级" ;; 4) echo "软件回滚" esac

    20.for循环

    依次将列表中的元素赋值给“变量名”,每次赋值后即执行一次循环体;知道列表中的元素耗尽,循环结束

    如果省略【in words】,此时使用位置参量

    #!/bin/bash
    sum=0
    for i in {1..100}
    do
    let sum+=i
    done
    echo "sum=$sum"
    for循环计算1..100

      for ((控制变量初始化;条件判断表达式;控制变量的修正表达式))

    do

    循环体

    #!/bin/bash
    for((sum=0,i=1;i<=100;sum+=i,i++))
    do
            true
    done
    echo $sum

     21.循环while

    while commands; do commands; done

    while condition; do

            循环体

    done

    condition:循环控制条件;进入循环之前,先做一次判断;每一次循环之后会再次做判断;条件为真,则执行一次循环;直到条件测试状态假,则终止循环,因此:condtion一般应有循环控制变量;而此变量的值在循环体不断地被修正

    进入条件:condition为true

    退出条件:condition为假

    无限循环

    while true; do

        循环体

    done

    while :; do

        循环体

    done

    #!/bin/bash
    sum=0
    i=1
    while ((i<=100)) ;do let sum+=i;let i++
    done
    echo $sum

    while特殊用法while read

    while read line;do

              循环体

    done < /path/from/somefile

    说明:依次读取/path/from/somefile文件中的每一行,且将行赋值给变量line

    [21:17:22 root@centos7 ~]$echo yang bo wen | while read x y z;do echo $x $y $z;done
    yang bo wen

     22.循环控制语句continue

    continue 【N】:提前结束第N层的本轮循环,而直接进入下一轮判断;最内层为第一层

    for ((i=0;i<3;i++));do
    for    ((j=0;j<4;j++));do
             [ $j -eq 2 ] && continue
            echo $j
    done
    echo -----------------------------
    done
    结束内圈循环

    [23:43:06 root@centos7 ~]$bash coun.sh
    0
    1
    3
    -----------------------------
    0
    1
    3
    -----------------------------
    0
    1
    3
    -----------------------------

     

    continue 2结束外圈循环

    for ((i=0;i<3;i++));do
    for    ((j=0;j<4;j++));do
             [ $j -eq 2 ] && continue 2
            echo $j
    done
    echo -----------------------------
    done
    结束外圈循环
    0
    1
    0
    1
    0
    1

    23.break

    提前结束第N个循环

    for ((i=0;i<3;i++));do
    for    ((j=0;j<4;j++));do
             [ $j -eq 2 ] && break
            echo $j
    done
    echo -----------------------------
    done
    结束内圈循环
    [23:51:35 root@centos7 ~]$bash coun.sh 
    0
    1
    -----------------------------
    0
    1
    -----------------------------
    0
    1
    -----------------------------

    break 2

    for ((i=0;i<3;i++));do
    for    ((j=0;j<4;j++));do
             [ $j -eq 2 ] && break 2
            echo $j
    done
    echo -----------------------------
    done
    直接结束外圈循环
    0
    1

    24 循环与菜单select

    select循环主要用于创建菜单,按数字顺序排列的菜单项显示在标准错误上,并显示PS3提示符等待用户输入

    select是个无线循环,因此要用break命令退出循环,或用exit命令终止脚本。select经常和case联合使用。

     
    [21:32:55 root@centos7 ~]$bash ybw.sh
    1) 北京老鸭
    2) 佛跳墙
    3) 小龙虾
    4) 羊蝎子
    5) 火锅
    6) 点才结束
    请点菜(1-6):

    #!/bin/bash
    sum=0
    PS3="请点菜(1-6):"
    select MENU in 北京老鸭 佛跳墙 小龙虾 羊蝎子 火锅 点才结束;do
        case $REPLY in
    (1)
    echo
    $MENU 价格是 100 let sum+=100 ;; (2) echo $MENU 价格是 88 let sum+=88 ;; (3) echo $MENU 价格是 66 let sum+=66 ;; (4) echo $MENU 价格是 166 let sum+=166 ;; (5) echo $MENU 价格是 200 let sum+=200 ;; (6) echo "点菜结束,退出" break ;; (*) echo "点菜错误,重新选择" ;; esac done echo "总价是:$sum"

    25.函数function

    函数function是由若干条shell命令组成的语句块,实现代码重用和模块化编程

    它与shell程序形式上是相似的,不同的是他不是一个单独的进程,不能独立运行,而是shell程序的一部分

    函数和shell程序区别

    shell程序在子shell中运行

    函数在当前shell中运行。因此在当前shell中,函数可对shell中变量进行修改

    函数由两部分组成:函数名和函数体

    declare -F
    查看当前已定义的函数名
    declare -f
    查看当前已定义的函数定义
    declare -f func_name
    查看指定当前已定义的函数名
    declare -F func_name
    查看当前已定义的函数名定义

     删除函数

    unset func_name

    交互式环境调用函数

    [22:13:23 root@centos7 ~]$you() {
    > echo "i am Spider-Man"
    > }
    [22:17:14 root@centos7 ~]$you
    i am Spider-Man

    实现判断Centos的主版本

    [22:21:57 root@centos7 ~]$kan() {
    > sed -nr 's/.* ([0-9].[0-9]).*/1/p' /etc/redhat-release
    > }
    [22:37:02 root@centos7 ~]$kan
    7.5

    脚本中定义及使用函数

    [22:42:11 root@centos7 ~]$bash li.sh 
    now going to the function hello
    hello there today is 2021-01-03
    back from the function
    
    #!/bin/bash
    hello() {
        echo "hello there today is `date +%F`"
    }
    echo "now going to the function hello"
    hello
    echo "back from the function"
    函数在使用前必须定义,因此应将函数定义放在脚本开始部分,直至shell首次发现后才能使用,调用函数仅使用其函数名即可
    source 接函数路径,输出函数名,即可调用函数
  • 相关阅读:
    笔试助攻题(思路)
    const 修饰成员函数 前后用法(effective c++ 03)
    UNIX 是啥?!和Linux什么关系?
    我的offer之路(一)
    我的offer之路(一)
    ANSI C 与 K&R C
    c内置数据类型
    预处理器
    小数用二进制如何表示
    C++中有三种创建对象的方法
  • 原文地址:https://www.cnblogs.com/aiyoubucuo/p/14117274.html
Copyright © 2011-2022 走看看