• 《Shell脚本学习指南》学习笔记之变量、判断和流程控制


    变量

    1. 定义变量
      可以使用export和readonly来设置变量,export用于修改或打印环境变量,readonly则使得变量不得修改。语法:
      export name[=word] ...
      readonly name[=word] ...
      可以export/readonly时就给变量赋值,或给变量赋值后再export/readonly变量,如:
      export website=oseye.net
      age=22
      export age
      比较常用的exoprt,它是把变量放进环境中,新的进程可以从其父进程继承环境,但继承后就是各自的,操作互不影响;而readonly不能被子进程继承。
      如打开终端,输入:
      a=b
      echo $a
      gnome-terminal
      这样会在打开的子进程的终端,你在新的终端试试:
      echo $a
      可以看到输出是“b”。
    2. 删除变量
      使用unset从当前的shell删除变量或函数,语法如下:
      unset [ -v ] variable ...
      unset -f function ....
      -v是默认选项,表示删除/接触指定的变量;
      -f解除或删除指定的函数;
    3. 使用变量
      除了在变量名之前加符号“$”使用变量外,还有更特殊的使用情况,这些变量名括在花括号里如${var},而且会增加额外的语法表达更丰富的含义。
      替换运算符
      运算符 替换
      ${varname:-word}

      如果varname存在且不是null,则返回其值;否则返回word。

      用途:如果变量未定义,则返回默认值。

      范例:如果count未定义,则${count:-0}的值为0。

      ${varname:=word}

      如果varname存在且不是null,则返回其值;否则,设置它的值设为word,并返回其值。

      用途:如果变量未定义,则设置变量为默认值。

      范例:如果count未定义,则${count:=0}设置count为0,并返回0。

      ${varname:?message}

      如果varname存在且不是null,则返回它的值;否则显示varname:message,并退出当前的命令或脚本。省略message会出现默认信息parameter null or not set(参数为空或未设置).

      用途:为了捕捉由于变量未定义所导致的错误。

      范例:${count:?"undefined!"}如果count未定义将显示“undefined!”且退出。

      ${varname:+word}

      如果varname存在且不是null,则返回word;否则返回null。

      用途:为测试变量是否存在。

      范例:如果count已定义,则${count:+1}返回1(也就是“真”)。


      模式匹配运算符

      下表中使用的模式(pattern)以及shell里其他的地方,例如case语句里所使用的模式都是shell的“通配符”模式,而不是正则表达式。
      表中假设path的值为/home/tolstoy/mem/long.file.name
      运算符 替换
      ${varname#pattern}

      从前面匹配,匹配成功则删除匹配的最短部分,并返回剩下的部分。

      例子:${path#/*/}

      结果:tolstoy/mem/long.file.name

      ${varname##pattern}

      从前面匹配,匹配成功则删除匹配的最长部分,并返回剩下的部分。

      例子:${path##/*/}

      结果:long.file.name

      ${varname%pattern}

      从后面匹配,匹配成功则删除匹配的最短部分,并返回剩下的部分。

      例子:${path#.*}

      结果:tolstoy/mem/long.file

      ${varname%%pattern}

      从后面匹配,匹配成功则删除匹配的最长部分,并返回剩下的部分。

      例子:${path##.*}

      结果:tolstoy/mem/long

    4. 位置参数
      所谓位置参数指的是Shell脚本的命令行参数,也表示在Shell函数内的函数参数,它的名称是以单个整数来命名,处于历史原因,当这个整数大于9时,需要用花括号({})括起来。
      除了使用整数来引用位置参数,还有一些特殊的变量:
      • $# 位置参数的总数;
      • $*,$@ 一次表示所有命令行参数,可以直接传递给函数或脚本;
      • "$*" 将所有的位置参数视为单个字符串,等同于"$1 $2 ...";
      • "$@" 将所有命令行参数视为单独个体,也就是单独字符串,等同于"$1" "$2" ...;
      POSIX还有一些内置的变量:
      • # 目前进程的参数个数。
      • @ 传递给当前进程的参数。置于双引号内,会展开为个别参数。
      • * 传递给当前进程的命令行参数,置于双括号内,展开时为一单独参数。
      • - 在引用时给的Shell 的选项。
      • ? 前一命令的退出状态。
      • $ shell的PID。
      • 0 shell程序的名字。
      • ! 最近一个后台命令的PID。可以此方式存储进程编号,然后通过wait命令同步。
      • HOME 主目录。
      • IFS 内部的字段分隔符,一般为制表符、空格、以及换行符。
      • LANG 当前locale的默认名称
      • LC_ALL 当前locale的名称。会覆盖LANG与其他LC_*变量。
      • LC_CTYPE 在模式匹配期间,用来确定字符类别的当前locale名称。
      • LC_MESSAGE 输出信息的当前语言名称。
      • LINENO 刚执行过的行在脚本或函数内的行编号。
      • NLSPATH 在$LC_MESSAGES(XSI)所给定的信息语言里,信息目录的位置。
      • PATH 命令查找的路径。
      • PPID 父进程的进程编号。
      • PS1 主要的命令提示字符串,默认为“$”。
      • PS2 行继续提示字符串默认">"。
      • PS4 以set -x设置的执行跟踪的提示字符串,默认为“+”。
      • PWD 当前工作目录。
    5. 算数运算符
      Shell的算术运算符与C语言里差不多,优先级顺序也相同。虽然有些是(包含)特殊字符,不过它们不需要以反斜杠转义,因为它们都置于$((...))语法中,这一语法如同双引号功能,除了内嵌双引号无须转义。
      运算符 意义 顺序
      ++ -- 增加及减少,可前置也可放在结尾 由左至右
      + - ! ~ 一元的正号与负号;逻辑与位的取反 由左至右
      + - * / % 加、减、乘、除、余 由左至右
      << >> 左移位、右移位 由左至右
      < <= > >= == != 比较 由左至右
      & | ^ 位的与、或、异或 由左至右
      && || 逻辑的与、或 由左至右
      ? : 条件表达式 由右至左

      = += -= *= /= %= &= ^=

      <<= >>= |=

      赋值运算符 由左至右
      用圆括号把字表达式语句括起来产生数字的结果1表示真,0表示假。对于逻辑的AND与OR运算符而言,任何的非0值函数都为真。

    退出状态

    每一条命令,不管是内置的、Shell函数,还是外部的,当它退出时,都会返回一个小的整数值给引用它的程序,这就是大家所熟知的程序退出状态。POSIX标准定义了退出状态及其含义:

    状态值 含义
    0 表示运行成功,程序执行未遇到任何问题
    1-125 表示运行失败,脚本命令、系统命令错误或参数传递错误
    126 找到了命令但无法执行
    127 未找到要运行的命令
    >128 命令被系统强行结束

    test命令

    test命令接受不同的参数用于测试各种条件是否成立,它还有一种等效形式:[ ... ],因此test的语法:

    test [ expression ]
    [ [ expression ] ]

    test命令的参数被描述为表达式,如下表:

    运算符 如果....则为真
    #一元表达式,运算符后边只有一个参数
    -b file file为块设备
    -c file file为字符设备
    -d file file为目录
    -e file file存在
    -f file file为一般文件
    -g file file属性位set- group-id置1
    -h file file为符号链接(与-L 同)
    -k file file设置了粘滞位(sticky bit)
    -L file file为符号链接(与-h同)
    -O file file用户拥有该文件
    -p file file为命名管道
    -r file file(对用户)可读
    -s file file不是空的(长度大于0字节)
    -S file file存在且为套接字(socket)
    -t fd file描述符与终端相关联
    -u file file属性位set-user-id置1
    -w file file(对用户)可写
    -x file file(对用户)可执行
    -n string 字符串是非null (长度大于0字节)
    -z string 字符串为空(长度为0字节)
    #二元表达式,运算符前后各有一个参数
    expr1 -a expr2 两个表达式皆为真(逻辑与)
    expr1 -o expr2 两个表达式至少有一个为真(逻辑或)
    ----------------------------------------------------------
    file1 -nt file2 第一个文件比第二个文件新(利用修改时间戳比较)
    file1 -ot file2 第一个文件比第二个文件旧(利用修改时间 戳比较)
    file1 -ef file2 两个文件由链接关联在一起(硬链接或符号链接)
    ----------------------------------------------------------
    var1 = var2 第一个字符串与第二个字符串相同
    var1 != var2 第一个字符串与第二个字符串不相同
    ----------------------------------------------------------
    var1 -eq var2 第一个整数与第二个整数相等
    var1 -ne var2 第一个整数不等于第二个整数
    var1 -lt var2 第一个整数小于第二个整数
    var1 -le var2 第一个整数小于或等于第二个整数量
    var1 -gt var2 第一个整数大于第二个整数
    var1 -ge var2 第一个整数大于或等于第二个整数
    • 所有shell变量都应该以引号括起来,这样即使shell变量展开后为null值,也不会出现问题!
    • -a和-o是test表达式之间,而&&和||是test之间的,要区分下。
    • 比较字符串是非常微妙的,因为字符串可能为空或减号开头,test命令会被混淆,所以通常在字符串前置字母X比如test "X$a" = "Xhe",当然了前置字母可以是任意的;
    • 只能做整数测试,而不能做任何浮点数测试;

    流程控制

    1. if语句
      if  条件
      then
        Command
      else
        Command
      fi
    2. case语句
      case $变量名 in
        模式1)
          命令序列1
          ;;
        模式2)
          命令序列2
          ;; 
        *)
          默认执行的命令序列
          ;; 
        esac 
      case语句结构特点如下:
      • case行尾必须为单词“in”,每一个模式必须以右括号“)”结束。
      • 双分号“;;”表示命令序列结束。
      • 匹配模式中可是使用方括号表示一个连续的范围,如[0-9];使用竖杠符号“|”表示或。
      • 最后的“*)”表示默认模式,当使用前面的各种模式均无法匹配该变量时,将执行“*)”后的命令序列。
    3. for语句
      for循环对一个变量的可能的值都执行一个命令序列。赋给变量的几个数值既可以在程序内以数值列表的形式提供,也可以在程序以外以位置参数的形式提供。for循环的一般格式为:
      for $变量名 [in 数值列表]
        do
          命令序列
        done
      变量名可以是用户选择的任何字符串,如果变量名是var,则在in之后给出的数值将顺序替换循环命令列表中的$var。如果省略了in,则变量var的取值将是位置参数。对变量的每一个可能的赋值都将执行do和done之间的命令列表。
    4. while和until
      while 和 until命令都是用命令的返回状态值来控制循环的.
      While 循环的一般格式为:
        while
            若干个命令行1
        do
            若干个命令行2
        done
      只要while的“若干个命令行1”中最后一个命令的返回状态为真,while循环就继续执行do...done之间的“若干个命令行2”。
      until命令是另一种循环结构,它和while命令相似,其格式如下:
       until
            若干个命令行1
        do
            若干个命令行2
        done
      until循环和while循环的区别在于:while循环在条件为真时继续执行循环,而until则是在条件为假时继续执行循环。
    5. break和continue
      break和continue命令分别用来退出循环或跳到循环体的其他地方,他们还可以接受参数,用来指出要退出或继续多少个被包含的循环,如
      while 条件(如:true)
      do ...
      	while 条件
      	do ...
      		break 2
      	done
      done
  • 相关阅读:
    ASP.NET 2.0个性化配置(profile)
    03 创建虚拟机
    一些新的Blender的视频教程
    [转载]虚拟家庭存档文件修改方法
    [转载]游戏开发中常用的设计模式
    批处理for命令详解(转)
    [转载]高效软件开发团队的特征
    软件构架师的特点
    一点SICP(Structure and Interpretation of Computer Programs) 资料 (转载加整理)
    [译]游戏编程入门(by David Astle)
  • 原文地址:https://www.cnblogs.com/zhaiqianfeng/p/4621295.html
Copyright © 2020-2023  润新知