Linux shell 脚本编程-高级篇 (七)

继 Linux shell 脚本编程-高级篇 (六)

7. 使用其他 shell


虽然 bash shell 是 Linux 发行版中最广泛使用的 shell,但它并不是唯一的选择。本节介绍另外两个可能会碰到的 shell: dash 和 zsh 。


7.1 什么是 dash shell


Debian 的 dash shell 是 ash shell 的直系后代,而 ash shell 则是 Unix 系统上原来的 Bourne shell 的简化版本。Kenneth Almquist 为 Unix 系统
开发了一个 Bourne shell 的简化版本,并将它命名为 Almquist shell,缩写为 ash。ash shell 最早的版本体积极小、速度奇快,但缺乏许多高级功能,
比如命令行编辑或命令使用记录功能,这使它很难用作交互式 shell。

NetBSD Unix 操作系统移植了 ash shell,直到今天依然将它用作默认 shell。NetBSD 开发人员对 ash shell进行了定制,增加了一些新的功能,使它更接
近 Bourne shell。新功能包括使用 emacs 和 vi 编辑器命令进行命令行编辑,利用历史命令来查看先前输入的命令。ash shell 的这个版本也被 FreeBSD
操作系统用作默认登录 shell。

Debian Linux 发行版创建了它自己的 ash shell版本(称作Debian ash,或dash)以供自用。dash 复制了ash shell 的 NetBSD版本的大多数功能,提供了
一些高级命令行编辑能力。

但实际上 dash shell 在许多基于 Debian 的 Linux发行版中并不是默认的 shell。由于 bash shell 在 Linux 中的流行,大多数基于 Debian 的 Linux
发行版将 bash shell 用作普通登录 shell,而只将 dash shell作为安装脚本的快速启动 shell,用于安装发行版文件。

流行的 Ubuntu 发行版是例外,给 Linux 环境中运行 shell 脚本带来了很多问题。Ubuntu Linux 发行版将 bash shell用作默认的交互 shell,但将 dash
shell用作默认的 /bin/sh shell。这个“特性”着实让shell脚本程序员一头雾水。

如前所述,每个shell脚本的起始行都必须声明脚本所用的 shell。在 bash shell 脚本中,我们一直用下面的行:

    #!/bin/bash

它会告诉 shell 使用位于 /bin/bash 的 shell 程序来执行脚本。在 Unix 世界中,默认 shell 一直是 /bin/sh。许多熟悉 Unix 环境的 shell 脚本程序
员会将这种用法带到他们的 Linux shell 脚本中:

    #!/bin/sh

在大多数 Linux发行版上,/bin/sh 文件是链接到 shell 程序 /bin/bash 的一个符号链接。这样就可以在无需修改的情况下,轻松地将为 Unix Bourne
shell 设计的 shell 脚本移植到 Linux环境中。

很遗憾,Ubuntu Linux 发行版将 /bin/sh 文件链接到了 shell程序 /bin/dash。由于 dash shell 只含有原来 Bourne shell中的一部分命令,这可能会
(而且经常会)让有些 shell 脚本无法正确工作。


7.2 dash shell 的特性
-----------------------------------------------------------------------------------------------------------------------------------------
尽管 bash shell 和 dash shell 都以 Bourne shell 为样板,但它们还是有一些差别的。

    NOTE:
    -------------------------------------------------------------------------------------------------------------------------------------
    如果系统上未安装 dash, 使用当前系统的包管理器安装。 下面是 Fedora 24 的安装指令:

        [devalone@devalone 22]$ sudo dnf install dash
    
    查看验证安装:
        [devalone@devalone 22]$ cat /etc/shells
        /bin/sh
        /bin/bash
        /sbin/nologin
        /usr/bin/sh
        /usr/bin/bash
        /usr/sbin/nologin
        /bin/dash
    
    进入 dash 子进程:
        [devalone@devalone 22]$ dash
        [devalone@devalone 22]$
        
        

7.2.1 dash 命令行参数
-----------------------------------------------------------------------------------------------------------------------------------------
dash shell 使用命令行参数来控制其行为。下表列出了命令行参数:


    dash 命令行参数
    +-------+-----------------------------------------------------------------------------------------------
    | 参 数    | 描 述
    +-------+-----------------------------------------------------------------------------------------------
    | -a    | 导出分配给shell的所有变量
    +-------+-----------------------------------------------------------------------------------------------
    | -c    | 从特定命令字符串中读取命令
    +-------+-----------------------------------------------------------------------------------------------
    | -e    | 如果是非交互式shell的话,在有未经测试的命令失败时立即退出        
    +-------+-----------------------------------------------------------------------------------------------
    | -f    | 显示路径名通配符
    +-------+-----------------------------------------------------------------------------------------------
    | -n    | 如果是非交互式shell的话,读取命令但不执行它们
    +-------+-----------------------------------------------------------------------------------------------
    | -u    | 在尝试展开一个未设置的变量时,将错误消息写出到STDERR
    +-------+-----------------------------------------------------------------------------------------------
    | -v    | 在读取输入时将输入写出到STDERR
    +-------+-----------------------------------------------------------------------------------------------
    | -x    | 在执行命令时将每个命令写出到STDERR
    +-------+-----------------------------------------------------------------------------------------------
    | -I    | 在交互式模式下,忽略输入中的EOF字符
    +-------+-----------------------------------------------------------------------------------------------
    | -i    | 强制shell运行在交互式模式下
    +-------+-----------------------------------------------------------------------------------------------
    | -m    | 启用作业控制(在交互式模式下默认开启)
    +-------+-----------------------------------------------------------------------------------------------
    | -s    | 从STDIN读取命令(在没有指定文件参数时的默认行为)
    +-------+-----------------------------------------------------------------------------------------------
    | -E    | 启用emacs命令行编辑器
    +-------+-----------------------------------------------------------------------------------------------
    | -V    | 启用vi命令行编辑器
    +-------+-----------------------------------------------------------------------------------------------

-E 命令行参数允许使用 emacs 编辑器命令进行命令行文本编辑。可以使用所有的 emacs 命令来处理一行中的文本,其中会用到 Ctrl和 Meta组合键。

-V 命令行参数允许使用 vi 编辑器命令进行命令行文本编辑。这个功能允许用 Esc 键在普通模式和 vi 编辑器模式之间切换。当在 vi模式中时,可以用
标准的 vi编辑器命令(例如,x 删除一个字符,i 插入文本)。完成命令行编辑后,必须再次按下 Esc键退出 vi编辑器模式。


7.2.2 dash 环境变量
-----------------------------------------------------------------------------------------------------------------------------------------
dash shell 用相当多的默认环境变量来记录信息,用户也可以创建自己的环境变量。


■ 默认环境变量
-----------------------------------------------------------------------------------------------------------------------------------------
dash 环境变量跟 bash 环境变量很像,不过,由于 dash 的目标是简洁,因此它的环境变量比 bash shell少多了。

dash shell用 set 命令来显示环境变量:

    $ set
    ANT_HOME='/usr/local/apache/ant'
    CATALINA_HOME='/home/devalone/programs/apache-tomcat-8.5.11'
    DBUS_SESSION_BUS_ADDRESS='unix:path=/run/user/1000/bus'
    HADOOP_HOME='/opt/hadoop/hadoop/hadoop'
    HISTCONTROL='ignoredups'
    HISTSIZE='1000'
    HOME='/home/devalone'
    HOSTNAME='devalone.sansovo.org'
    IFS='
    '
    JAVA_HOME='/usr/java/latest'
    .....


■ 位置参数
-----------------------------------------------------------------------------------------------------------------------------------------
除了默认环境变量,dash shell 还给命令行上定义的参数分配了特殊变量。下面是 dash shell 中用到的位置参数变量:

    □ $0:shell的名称。
    □ $n:第n个位置参数。
    □ $*:含有所有参数内容的单个值,由IFS环境变量中的第一个字符分隔;没定义IFS的话,由空格分隔。
    □ $@:将所有的命令行参数展开为多个参数。
    □ $#:位置参数的总数。
    □ $?:最近一个命令的退出状态码。
    □ $-:当前选项标记。
    □ $$:当前 shell的进程ID(PID)。
    □ $!:最近一个后台命令的PID。

所有 dash 的位置参数都类似于 bash shell 中的位置参数。可以在 shell 脚本中使用位置参数,和 bash shell中的用法一样。


■ 用户自定义的环境变量
-----------------------------------------------------------------------------------------------------------------------------------------
dash shell 允许定义自己的环境变量。与 bash一样,可以在命令行上用赋值语句来定义新的环境变量。

示例:
    $ testing=10; export testing
    $ echo $testing
    10
    $

如果不用 export 命令,用户自定义的环境变量就只在当前 shell 或进程中可见。

    NOTE:
    -------------------------------------------------------------------------------------------------------------------------------------
    dash 变量和 bash 变量之间有一个巨大的差异。dash shell 不支持数组。

 

7.2.3 dash 内建命令
-----------------------------------------------------------------------------------------------------------------------------------------
跟 bash shell 一样,dash shell 含有一组它能识别的内建命令。可以在命令行界面上直接使用这些命令,或者将其放到 shell脚本中。

    dash shell 内建命令
    +-----------+-----------------------------------------------------------------------------------------------
    | 命 令        | 描 述
    +-----------+-----------------------------------------------------------------------------------------------
    | alias        | 创建代表文本字符串的别名字符串
    +-----------+-----------------------------------------------------------------------------------------------
    | bg        | 以后台模式继续执行指定的作业
    +-----------+-----------------------------------------------------------------------------------------------
    | cd        | 切换到指定的目录
    +-----------+-----------------------------------------------------------------------------------------------
    | echo        | 显示文本字符串和环境变量
    +-----------+-----------------------------------------------------------------------------------------------
    | eval        | 将所有参数用空格连起来①
    +-----------+-----------------------------------------------------------------------------------------------
    | exec        | 用指定命令替换shell进程
    +-----------+-----------------------------------------------------------------------------------------------
    | exit        | 终止shell进程
    +-----------+-----------------------------------------------------------------------------------------------
    | export    | 导出指定的环境变量,供子shell使用
    +-----------+-----------------------------------------------------------------------------------------------
    | fg        | 以前台模式继续执行指定的作业
    +-----------+-----------------------------------------------------------------------------------------------
    | getopts    | 从参数列表中中提取选项和参数
    +-----------+-----------------------------------------------------------------------------------------------
    | hash        | 维护并提取最近执行的命令及其位置的哈希表
    +-----------+-----------------------------------------------------------------------------------------------
    | pwd        | 显示当前工作目录
    +-----------+-----------------------------------------------------------------------------------------------
    | read        | 从STDIN读取一行并将其赋给一个变量
    +-----------+-----------------------------------------------------------------------------------------------
    | readonly    | 从STDIN读取一行并赋给一个只读变量
    +-----------+-----------------------------------------------------------------------------------------------
    | printf    | 用格式化字符串显示文本和变量
    +-----------+-----------------------------------------------------------------------------------------------
    | set        | 列出或设置选项标记和环境变量
    +-----------+-----------------------------------------------------------------------------------------------
    | shift        | 按指定的次数移动位置参数
    +-----------+-----------------------------------------------------------------------------------------------
    | test        | 测试一个表达式,成立的话返回0,不成立的话返回1
    +-----------+-----------------------------------------------------------------------------------------------
    | times        | 显示当前shell和所有shell进程的累计用户时间和系统时间
    +-----------+-----------------------------------------------------------------------------------------------
    | trap        | 在shell收到某个指定信号时解析并执行命令
    +-----------+-----------------------------------------------------------------------------------------------
    | type        | 解释指定的名称并显示结果(别名、内建、命令或关键字)
    +-----------+-----------------------------------------------------------------------------------------------
    | ulimit    | 查询或设置进程限制
    +-----------+-----------------------------------------------------------------------------------------------
    | umask        | 设置文件和目录的默认权限
    +-----------+-----------------------------------------------------------------------------------------------
    | unalias    | 删除指定的别名
    +-----------+-----------------------------------------------------------------------------------------------
    | unset        | 从导出的变量中删除指定的变量或选项标记
    +-----------+-----------------------------------------------------------------------------------------------
    | wait        | 等待指定的作业完成,然后返回退出状态码
    +-----------+-----------------------------------------------------------------------------------------------
    ① 这条命令的重点在于将所有参数用空格连接起来之后,它会重新解析并执行这条命令。

dash shell 支持许多和 bash shell 一样的内建命令。其中没有操作命令历史记录或目录栈的命令。dash shell 不支持这些特性。


7.3 dash 脚本编程
-----------------------------------------------------------------------------------------------------------------------------------------
dash shell 不能识别 bash shell 的所有脚本编程功能。为 bash 环境编写的脚本在 dash shell 中通常会运行失败。


7.3.1 创建 dash 脚本
-----------------------------------------------------------------------------------------------------------------------------------------
为 dash shell 编写脚本和为 bash shell 编写脚本非常类似。一定要在脚本中指定要用哪个 shell,保证脚本是用正确的 shell 运行的。

可以在shell脚本的第一行指定:

    #!/bin/dash

还可以在这行指定 shell 命令行参数,如(7.2.1 dash 命令行参数) 所示。

 

7.3.2 不能使用的功能
-----------------------------------------------------------------------------------------------------------------------------------------
很遗憾,由于 dash shell 只是 Bourne shell 功能的一个子集, bash shell 脚本中的有些功能没法在 dash shell 中使用。这些通常被称作 bash 主义
(bashism)。本节将简单总结在 bash shell脚本中习惯使用但在 dash shell 环境中没法工作的 bash shell功能。


■ 算术运算
-----------------------------------------------------------------------------------------------------------------------------------------
bash shell 脚本中三种进行数学运算的方法:

    □ 使用expr命令    :expr operation
    □ 使用方括号    :$[ operation ]
    □ 使用双圆括号    :$(( operation ))

dash shell 支持 expr命令和双圆括号方法,但不支持方括号方法。如果有大量采用方括号形式的数学运算的话,这可能是个问题。

在 dash shell 脚本中执行算术运算的正确格式是用双圆括号方法。

示例:
    $ cat test5b.sh
    #!/bin/dash
    # testing mathematical operations
    value1=10
    value2=15

    value3=$(( $value1 * $value2 ))
    echo "The answer is $value3"
    $ chmod a+x test5b.sh
    $ ./test5b.sh
    The answer is 150
    $

■ test 命令
-----------------------------------------------------------------------------------------------------------------------------------------
虽然 dash shell支持 test命令,但必须注意它的用法。bash shell版本的 test命令与 dash shell 版本的略有不同。

bash shell的test命令允许使用双等号(==)来测试两个字符串是否相等。这是为了照顾习惯在其他编程语言中使用这种格式的程序员而加上去的。

但是,dash shell中的 test命令不能识别用作文本比较的==符号,只能识别=符号。如果在 bash脚本中使用了==符号,就得将文本比较符号改成单个的等号。

示例:
    $ cat test7.sh
    #!/bin/dash
    # testing the = comparison

    test1=abcdef
    test2=abcdef

    if [ $test1 = $test2 ]
    then
            echo "They are the same"
    else
            echo "They are different"
    fi
    $ chmod a+x test7.sh
    $ ./test7.sh
    They are the same
    $

■ function 命令
-----------------------------------------------------------------------------------------------------------------------------------------
bash shell支持两种定义函数的方法:

    □ 使用function()语句
    □ 只使用函数名

dash shell 不支持 function 语句。在 dash shell中,必须用函数名和圆括号定义函数。

如果脚本可能会用在 dash 环境中,就必须使用函数名来定义函数,决不能使用 function()语句。

示例:
    $ cat test10.sh
    #!/bin/dash
    # testing functions

    func1() {
            echo "This is an example of a function"
    }

    count=1
    while [ $count -le 5 ]
    do
            func1
            count=$(( $count + 1 ))
    done
    echo "This is the end of the loop"
    func1
    echo "This is the end of the script"
    $ chmod a+x test10.sh
    $ ./test10.sh
    This is an example of a function
    This is an example of a function
    This is an example of a function
    This is an example of a function
    This is an example of a function
    This is the end of the loop
    This is an example of a function
    This is the end of the script

 

7.4 zsh shell
-----------------------------------------------------------------------------------------------------------------------------------------
Z shell(称作 zsh shell) 是由 Paul Falstad开发的一个开源 Unix shell。它汲取了所有现有 shell 的设计理念并增加了许多独到的功能,为程序员创建
了一个无所不能的高级 shell。

下面是zsh shell的一些独特的功能:

    □ 改进的shell选项处理
    □ shell兼容性模式
    □ 可加载模块

在这些功能中,可加载模块是 shell 设计中最先进的功能。在 bash 和 dash shell 中已经看到过,每种 shell 都包含一组内建命令,这些命令无需借助
外部工具程序就可以使用。内建命令的好处在于执行速度快。shell 不必在运行命令前先加载一个工具程序。内建命令已经在内存中了,随时可用。

zsh shell 提供了一组核心内建命令,并提供了添加额外命令模块(command module)的能力。每个命令模块都为特定场景提供了另外一组内建命令,比如
网络支持和高级数学功能。可以只添加觉得有用的模块。

这个功能提供了一个极佳的方式:在需要较小 shell 体积和较少命令时限制 zsh shell的体积,在需要更快执行速度时增加可用的内建命令数量。

    NOTE:
    -------------------------------------------------------------------------------------------------------------------------------------
    如果系统上未安装 zsh, 使用当前系统的包管理器安装。下面是 Fedora 24 的安装指令:
    
        [devalone@devalone 22]$ sudo dnf install zsh
    
    查看验证 zsh 已安装成功:
        [devalone@devalone 22]$ cat /etc/shells
        /bin/sh
        /bin/bash
        /sbin/nologin
        /usr/bin/sh
        /usr/bin/bash
        /usr/sbin/nologin
        /bin/dash
        /usr/bin/zsh
        /bin/zsh
    
    进入 zsh 子进程:
    
        [devalone@devalone 22]$ zsh
    
7.5 zsh shell 的组成
-----------------------------------------------------------------------------------------------------------------------------------------

 

7.5.1 zsh shell 选项
-----------------------------------------------------------------------------------------------------------------------------------------
大多数 shell 采用命令行参数来定义 shell 的行为。zsh shell使用了一些命令行参数来定义 shell的操作,但大多数情况下它用选项来定制 shell的行为。
可以在命令行上或在 shell中用 set命令设置 shell选项。

    zsh shell命令行参数
    +-----------+--------------------------------------------------------------------------------
    | 参 数        | 描 述
    +-----------+--------------------------------------------------------------------------------
    | -c        | 只执行指定的命令,然后退出
    +-----------+--------------------------------------------------------------------------------
    | -i        | 作为交互式shell启动,提供一个命令行交互提示符
    +-----------+--------------------------------------------------------------------------------
    | -s        | 强制shell从STDIN读取命令
    +-----------+--------------------------------------------------------------------------------
    | -o        | 指定命令行选项
    +-----------+--------------------------------------------------------------------------------

虽然这看起来像是一小组命令行参数,但 -o 参数有些容易让人误解。它允许设置 shell 选项来定义 shell 的功能。到目前为止,zsh shell是所有shell
中可定制性最强的。可以更改很多 shell 环境的特性。不同的选项可以分成以下几大类:

    □ 更改目录    :该选项用于控制cd命令和dirs命令如何处理目录更改。
    □ 补全        :该选项用于控制命令补全功能。
    □ 扩展和扩展匹配:该选项用于控制命令中文件扩展。
    □ 历史记录    :该选项用于控制命令历史记录。
    □ 初始化    :该选项用于控制shell在启动时如何处理变量和启动文件。
    □ 输入输出    :该选项用于控制命令处理。
    □ 作业控制    :该选项用于控制shell如何处理作业和启动作业。
    □ 提示        :该选项用于控制shell如何处理命令行提示符。
    □ 脚本和函数:该选项用于控制shell如何处理shell脚本和定义函数。
    □ shell仿真    :该选项允许设置zsh shell来模拟其他类型shell行为。
    □ shell状态    :该选项用于定义启动哪种shell的选项。
    □ zle        :该选项用于控制zsh行编辑器功能。
    □ 选项别名    :可以用作其他选项别名的特殊选项。


7.5.2 zsh shell 内建命令
-----------------------------------------------------------------------------------------------------------------------------------------
zsh shell 的独到之处在于它允许扩展 shell 中的内建命令。这为许多不同的应用程序提供了大量的快速工具。


■ zsh 核心内建命令
-----------------------------------------------------------------------------------------------------------------------------------------
zsh shell 的核心包括一些在其他 shell中已经见到过的基本内建命令。下表列出可用的内建命令:

    zsh 核心内建命令
    +-----------+-----------------------------------------------------------------------------------------------
    | 命 令        | 描 述
    +-----------+-----------------------------------------------------------------------------------------------
    | alias        | 为命令和参数定义一个替代性名称
    +-----------+-----------------------------------------------------------------------------------------------
    | autoload    | 将shell函数预加载到内存中以便快速访问
    +-----------+-----------------------------------------------------------------------------------------------
    | bg        | 以后台模式执行一个作业
    +-----------+-----------------------------------------------------------------------------------------------
    | bindkey    | 将组合键和命令绑定到一起
    +-----------+-----------------------------------------------------------------------------------------------
    | builtin    | 执行指定的内建命令而不是同样名称的可执行文件
    +-----------+-----------------------------------------------------------------------------------------------
    | bye        | 跟exit相同
    +-----------+-----------------------------------------------------------------------------------------------
    | cd        | 切换当前工作目录
    +-----------+-----------------------------------------------------------------------------------------------
    | chdir        | 切换当前工作目录
    +-----------+-----------------------------------------------------------------------------------------------
    | command    | 将指定命令当作外部文件执行而不是函数或内建命令
    +-----------+-----------------------------------------------------------------------------------------------
    | declare    | 设置变量的数据类型(同typeset)
    +-----------+-----------------------------------------------------------------------------------------------
    | dirs        | 显示目录栈的内容
    +-----------+-----------------------------------------------------------------------------------------------
    | disable    | 临时禁用指定的散列表元素
    +-----------+-----------------------------------------------------------------------------------------------
    | disown    | 从作业表中移除指定的作业
    +-----------+-----------------------------------------------------------------------------------------------
    | echo        | 显示变量和文本
    +-----------+-----------------------------------------------------------------------------------------------
    | emulate    | 用zsh来模拟另一个shell,比如Bourne、Korn或C shell
    +-----------+-----------------------------------------------------------------------------------------------
    | enable    | 使能指定的散列表元素
    +-----------+-----------------------------------------------------------------------------------------------
    | eval        | 在当前shell进程中执行指定的命令和参数
    +-----------+-----------------------------------------------------------------------------------------------
    | exec        | 执行指定的命令和参数来替换当前shell进程
    +-----------+-----------------------------------------------------------------------------------------------
    | exit        | 退出shell并返回指定的退出状态码。如果没有指定,使用最后一条命令的退出状态码
    +-----------+-----------------------------------------------------------------------------------------------
    | export    | 允许在子shell进程中使用指定的环境变量名及其值
    +-----------+-----------------------------------------------------------------------------------------------
    | false        | 返回退出状态码1
    +-----------+-----------------------------------------------------------------------------------------------
    | fc        | 从历史记录中选择某范围内的命令
    +-----------+-----------------------------------------------------------------------------------------------
    | fg        | 以前台模式执行指定的作业
    +-----------+-----------------------------------------------------------------------------------------------
    | float        | 将指定变量设为保存浮点值的变量
    +-----------+-----------------------------------------------------------------------------------------------
    | functions    | 将指定名称设为函数
    +-----------+-----------------------------------------------------------------------------------------------
    | getln        | 从缓冲栈中读取下一个值并将其放到指定变量中
    +-----------+-----------------------------------------------------------------------------------------------
    | getopts    | 提取命令行参数中的下一个有效选项并将它放到指定变量中
    +-----------+-----------------------------------------------------------------------------------------------
    | hash        | 直接修改命令哈希表的内容
    +-----------+-----------------------------------------------------------------------------------------------
    | history    | 列出历史记录文件中的命令
    +-----------+-----------------------------------------------------------------------------------------------
    | integer    | 将指定变量设为整数类型
    +-----------+-----------------------------------------------------------------------------------------------
    | jobs        | 列出指定作业的信息,或分配给shell进程的所有作业
    +-----------+-----------------------------------------------------------------------------------------------
    | kill        | 向指定进程或作业发送信号(默认为SIGTERM)
    +-----------+-----------------------------------------------------------------------------------------------
    | let        | 执行算术运算并将结果赋给一个变量
    +-----------+-----------------------------------------------------------------------------------------------
    | limit        | 设置或显示资源限制
    +-----------+-----------------------------------------------------------------------------------------------
    | local        | 为指定变量设置数据属性
    +-----------+-----------------------------------------------------------------------------------------------
    | log        | 显示受watch参数①影响的当前登录到系统上的所有用户
    +-----------+-----------------------------------------------------------------------------------------------
    | logout    | 同exit,但只在shell是登录shell时有效
    +-----------+-----------------------------------------------------------------------------------------------
    | popd        | 从目录栈中删除下一项
    +-----------+-----------------------------------------------------------------------------------------------
    | print        | 显示变量和文本
    +-----------+-----------------------------------------------------------------------------------------------
    | printf    | 用C风格的格式字符串来显示变量和文本
    +-----------+-----------------------------------------------------------------------------------------------
    | pushd        | 改变当前工作目录,并将上一个目录放到目录栈中
    +-----------+-----------------------------------------------------------------------------------------------
    | pushln    | 将指定参数放到编辑缓冲栈中
    +-----------+-----------------------------------------------------------------------------------------------
    | pwd        | 显示当前工作目录的完整路径名
    +-----------+-----------------------------------------------------------------------------------------------
    | read        | 读取一行,并用IFS变量将数据字段赋给指定变量
    +-----------+-----------------------------------------------------------------------------------------------
    | readonly    | 将值赋给不能修改的变量
    +-----------+-----------------------------------------------------------------------------------------------
    | rehash    | 重建命令散列表
    +-----------+-----------------------------------------------------------------------------------------------
    | set        | 为shell设置选项或位置参数
    +-----------+-----------------------------------------------------------------------------------------------
    | setopt    | 为shell设置选项
    +-----------+-----------------------------------------------------------------------------------------------
    | shift        | 读取并删除第一个位置参数,然后将剩余的参数向前移动一个位置
    +-----------+-----------------------------------------------------------------------------------------------
    | source    | 找到指定文件并将其内容复制到当前位置
    +-----------+-----------------------------------------------------------------------------------------------
    | suspend    | 挂起shell的执行,直到它收到SIGCONT信号
    +-----------+-----------------------------------------------------------------------------------------------
    | test        | 如果指定条件为TRUE的话,返回退出状态码0
    +-----------+-----------------------------------------------------------------------------------------------
    | times        | 显示当前shell以及shell中所有运行进程的累计用户时间和系统时间
    +-----------+-----------------------------------------------------------------------------------------------
    | trap        | 阻断指定信号从而让shell无法处理,如果收到信号则执行指定命令
    +-----------+-----------------------------------------------------------------------------------------------
    | true        | 返回退出状态码0
    +-----------+-----------------------------------------------------------------------------------------------
    | ttyctl    | 锁定和解锁显示
    +-----------+-----------------------------------------------------------------------------------------------
    | type        | 显示shell会如何解释指定的命令
    +-----------+-----------------------------------------------------------------------------------------------
    | typeset    | 设置或显示变量的特性
    +-----------+-----------------------------------------------------------------------------------------------
    | ulimit    | 设置或显示shell或shell中运行进程的资源限制
    +-----------+-----------------------------------------------------------------------------------------------
    | umask        | 设置或显示创建文件和目录的默认权限
    +-----------+-----------------------------------------------------------------------------------------------
    | unalias    | 删除指定的命令别名
    +-----------+-----------------------------------------------------------------------------------------------
    | unfunction| 删除指定的已定义函数
    +-----------+-----------------------------------------------------------------------------------------------
    | unhash    | 删除散列表中的指定命令
    +-----------+-----------------------------------------------------------------------------------------------
    | unlimit    | 取消指定的资源限制
    +-----------+-----------------------------------------------------------------------------------------------
    | unset        | 删除指定的变量特性
    +-----------+-----------------------------------------------------------------------------------------------
    | unsetopt    | 删除指定的shell选项
    +-----------+-----------------------------------------------------------------------------------------------
    | wait        | 等待指定的作业或进程完成
    +-----------+-----------------------------------------------------------------------------------------------
    | whence    | 显示指定命令会如何被shell解释
    +-----------+-----------------------------------------------------------------------------------------------
    | where        | 如果shell找到的话,显示指定命令的路径名
    +-----------+-----------------------------------------------------------------------------------------------
    | which        | 用csh风格的输出显示指定命令的路径名
    +-----------+-----------------------------------------------------------------------------------------------
    | zcompile    | 编辑指定的函数或脚本,加速自动加载
    +-----------+-----------------------------------------------------------------------------------------------
    | zmodload    | 对可加载zsh模块执行特定操作
    +-----------+-----------------------------------------------------------------------------------------------

zsh shell在提供内建命令方面太强大了,可以根据 bash 中对应的命令来识别出其中的大多数命令。zsh shell内建命令最重要的功能是模块。


■ zsh 附加模块
-----------------------------------------------------------------------------------------------------------------------------------------
有大量的模块可以为 zsh shell提供额外的内建命令,而且这个数量还在随着程序员不断增加新模块而不断增长。下表列出了当前比较流行的模块。


    zsh 模块
    +-------------------+------------------------------------------------------------------------------------------
    | 模 块                | 描 述
    +-------------------+------------------------------------------------------------------------------------------
    | zsh/datetime        | 额外的日期和时间命令及变量
    +-------------------+------------------------------------------------------------------------------------------
    | zsh/files            | 基本的文件处理命令
    +-------------------+------------------------------------------------------------------------------------------
    | zsh/mapfile        | 通过关联数组来访问外部文件
    +-------------------+------------------------------------------------------------------------------------------
    | zsh/mathfunc        | 额外的科学函数
    +-------------------+------------------------------------------------------------------------------------------
    | zsh/pcre            | 扩展的正则表达式库
    +-------------------+------------------------------------------------------------------------------------------
    | zsh/net/socket    | Unix域套接字支持
    +-------------------+------------------------------------------------------------------------------------------
    | zsh/stat            | 访问stat系统调用来提供系统的统计状况
    +-------------------+------------------------------------------------------------------------------------------
    | zsh/system        | 访问各种底层系统功能的接口
    +-------------------+------------------------------------------------------------------------------------------
    | zsh/net/tcp        | 访问TCP套接字
    +-------------------+------------------------------------------------------------------------------------------
    | zsh/zftp            | 专用FTP客户端命令
    +-------------------+------------------------------------------------------------------------------------------
    | zsh/zselect        | 阻塞,直到文件描述符就绪才返回
    +-------------------+------------------------------------------------------------------------------------------
    | zsh/zutil            | 各种shell实用工具
    +-------------------+------------------------------------------------------------------------------------------

zsh shell模块涵盖了很多方面的功能,从简单的命令行编辑功能到高级网络功能。zsh shell 的思想是提供一个基本的、最小化的 shell环境,让用户在
编程时再添加需要的模块。


■ 查看、添加和删除模块
-----------------------------------------------------------------------------------------------------------------------------------------
zmodload 命令是 zsh 模块的管理接口。可以在 zsh shell 会话中用这个命令查看、添加或删除模块。

zmodload 命令不加任何参数会显示zsh shell中当前已安装的模块:

    [devalone@devalone]~/study/shell-script/22% zmodload
    zsh/complete
    zsh/files
    zsh/main
    zsh/zle
    zsh/zutil

不同的 zsh shell 实现在默认情况下包含了不同的模块。要添加新模块,只需在 zmodload 命令行上指定模块名称就行了。

示例:
    [devalone@devalone]~/study/shell-script/22% zmodload zsh/zftp

不会有信息表明模块已经加载成功了。可以再运行一下 zmodload 命令,新添加的模块会出现在已安装模块的列表中。

示例:
    [devalone@devalone]~/study/shell-script/22% zmodload
    zsh/complete
    zsh/files
    zsh/main
    zsh/net/tcp
    zsh/zftp
    zsh/zle
    zsh/zutil
    
    
一旦加载了模块,该模块中的命令就成为了可用的内建命令。

示例:
    % zftp open myhost.com devalone testing1
    Welcome to the myhost FTP server.
    % zftp cd test
    % zftp dir
    01-21-11 11:21PM 120823 test1
    01-21-11 11:23PM 118432 test2
    % zftp get test1 > test1.txt
    % zftp close


zftp 命令允许直接在 zsh shell命令行操作完整的FTP会话!可以在 zsh shell 脚本中使用这些命令,直接在脚本中进行文件传输。

要删除已安装的模块,用 -u 参数和模块名。

示例:
    [devalone@devalone]~/study/shell-script/22% zmodload -u zsh/zftp

    NOTE:
    -------------------------------------------------------------------------------------------------------------------------------------
    通常习惯将 zmodload 命令放进 $HOME/.zshrc启动文件中,这样在 zsh启动时常用的函数就会自动加载。

    
    
7.6 zsh 脚本编程
-----------------------------------------------------------------------------------------------------------------------------------------
zsh shell的主要目的是为 shell程序员提供一个高级编程环境。认识到这点,就能理解为什么 zsh shell会提供那么多方便脚本编程的功能。


7.6.1 数学运算
-----------------------------------------------------------------------------------------------------------------------------------------
zsh shell可以轻松执行数学函数。zsh shell在所有数学运算中都提供了对浮点数的全面支持。


■ 执行计算
-----------------------------------------------------------------------------------------------------------------------------------------
zsh shell 提供了执行数学运算的两种方法:

    □ let命令
    □ 双圆括号

在使用 let 命令时,应该在算式前后加上双引号,这样才能使用空格。

示例:
    [devalone@devalone]~/study/shell-script/22% let value1=" 4 * 5.1 /3.2 "
    [devalone@devalone]~/study/shell-script/22% echo $value1
    6.3750000000

注意,使用浮点数会带来精度问题。为了解决这个问题,通常要使用 printf 命令,并指定能正确显示结果所需的小数点精度。

示例:
    [devalone@devalone]~/study/shell-script/22% printf "%6.3f\n" $value1
     6.375
    [devalone@devalone]~/study/shell-script/22% printf "%-6.3f\n" $value1
    6.375
    
第二个指令强制左对齐。

第二种方法是使用双圆括号。

示例: 结合了两种定义数学运算的方法

    [devalone@devalone]~/study/shell-script/22% value1=$(( 4 * 5.1 ))
    [devalone@devalone]~/study/shell-script/22% (( value2 = 4 * 5.1 ))
    [devalone@devalone]~/study/shell-script/22% printf "%6.3f\n" $value1 $value2
    20.400
    20.400

注意,可以将双圆括号放在算式两边(前面加个美元符)或整个赋值表达式两边。两种方法输出同样的结果。

如果一开始没用 typeset 命令来声明变量的数据类型,那么 zsh shell 会尝试自动分配数据类型。

示例:
    [devalone@devalone]~/study/shell-script/22% value1=10
    [devalone@devalone]~/study/shell-script/22% value2=$(( $value1 / 3 ))
    [devalone@devalone]~/study/shell-script/22% echo $value2
    3.3333333333

被当做浮点数类型。


■ 数学函数
-----------------------------------------------------------------------------------------------------------------------------------------
在 zsh shell中,内建数学函数可多可少。默认的 zsh并不含有任何特殊的数学函数。但如果安装了 zsh/mathfunc模块,就会拥有远远超出需要的数学函数。

示例:
    [devalone@devalone]~/study/shell-script/22% zmodload
    zsh/complete
    zsh/files
    zsh/main
    zsh/net/tcp
    zsh/zle
    zsh/zutil
    [devalone@devalone]~/study/shell-script/22% value1=$(( sqrt(9) ))
    zsh: unknown function: sqrt

    [devalone@devalone]~/study/shell-script/22% zmodload zsh/mathfunc
    [devalone@devalone]~/study/shell-script/22% value1=$(( sqrt(9) ))
    [devalone@devalone]~/study/shell-script/22% echo $value1
    3.0000000000

现在拥有了一个完整的数学函数库。

    NOTE:
    -------------------------------------------------------------------------------------------------------------------------------------
    zsh中支持很多数学函数。要查看 zsh/mathfunc模块提供的所有数学函数的清单,可以参看 zsh模块的手册页面。


    
7.6.2 结构化命令
-----------------------------------------------------------------------------------------------------------------------------------------
zsh shell 为 shell 脚本提供了常用的结构化命令:

    □ if-then-else语句
    □ for循环(包括C语言风格的)
    □ while循环
    □ until循环
    □ select语句
    □ case语句

zsh 中的每个结构化命令采用的语法都跟 bash shell 中的一样。zsh shell 还包含了另外一个 repeat 的结构化命令。

repeat 命令使用如下格式:

    repeat param
    do
        commands
    done

param 参数必须是一个数字或能算出一个数值的数学算式。repeat 命令就会执行指定的命令那么多次。

示例:
    [devalone@devalone]~/study/shell-script/23% cat test1.sh
    #!/bin/zsh
    # using the repeat command

    value1=$(( 10 / 2 ))
    repeat $value1
    do
            echo "This is a test"
    done

    [devalone@devalone]~/study/shell-script/23% ./test1.sh
    This is a test
    This is a test
    This is a test
    This is a test
    This is a test
    

7.6.3 函数
-----------------------------------------------------------------------------------------------------------------------------------------
zsh shell支持使用 function 命令或通用圆括号定义函数名的方式来创建自定义函数。

示例:
    [devalone@devalone]~/study/shell-script/23% functest2(){
    function> echo "This is the test2 function"}
    [devalone@devalone]~/study/shell-script/23% functest2
    This is the test2 function

    

                                                                                 (本篇完)

 

系列目录:

Linux shell 脚本编程-高级篇 (一)

Linux shell 脚本编程-高级篇 (二)

Linux shell 脚本编程-高级篇 (三)

Linux shell 脚本编程-高级篇 (四)

Linux shell 脚本编程-高级篇 (五)

Linux shell 脚本编程-高级篇 (六)

Linux shell 脚本编程-高级篇 (七)

 

 

-----------------------------------------------------------------------------------------------------------------------------------------
参考:

    《Linux 命令行与 shell 脚本编程大全》 第 3 版 —— 2016.8(美)Richard Blum  Cristine Bresnahan

你可能感兴趣的:(Linux,操作系统,CentOS7,Fedora)