• Shell基础语法——命令


    内建命令(内置命令)

    所谓 Shell 内建命令,就是由 Bash 自身提供的命令,而不是文件系统中的某个可执行文件。可以使用 type 来确定一个命令是否是内建命令。

    通常来说,内建命令会比外部命令执行得更快,执行外部命令时不但会触发磁盘 I/O,还需要 fork 出一个单独的进程来执行,执行完成后再退出。而执行内建命令相当于调用当前 Shell 进程的一个函数。

    Bash Shell 内建命令
    命令说明
    :扩展参数列表,执行重定向操作
    .读取并执行指定文件中的命令(在当前 shell 环境中)
    alias为指定命令定义一个别名
    bg将作业以后台模式运行
    bind将键盘序列绑定到一个 readline 函数或宏
    break退出 for、while、select 或 until 循环
    builtin执行指定的 shell 内建命令
    caller返回活动子函数调用的上下文
    cd将当前目录切换为指定的目录
    command执行指定的命令,无需进行通常的 shell 查找
    compgen为指定单词生成可能的补全匹配
    complete显示指定的单词是如何补全的
    compopt修改指定单词的补全选项
    continue继续执行 for、while、select 或 until 循环的下一次迭代
    declare声明一个变量或变量类型。
    dirs显示当前存储目录的列表
    disown从进程作业表中刪除指定的作业
    echo将指定字符串输出到 STDOUT
    enable启用或禁用指定的内建shell命令
    eval将指定的参数拼接成一个命令,然后执行该命令
    exec用指定命令替换 shell 进程
    exit强制 shell 以指定的退出状态码退出
    export设置子 shell 进程可用的变量
    fc从历史记录中选择命令列表
    fg将作业以前台模式运行
    getopts分析指定的位置参数
    hash查找并记住指定命令的全路径名
    help显示帮助文件
    history显示命令历史记录
    jobs列出活动作业
    kill向指定的进程 ID(PID) 发送一个系统信号
    let计算一个数学表达式中的每个参数
    local在函数中创建一个作用域受限的变量
    logout退出登录 shell
    mapfile从 STDIN 读取数据行,并将其加入索引数组
    popd从目录栈中删除记录
    printf使用格式化字符串显示文本
    pushd向目录栈添加一个目录
    pwd显示当前工作目录的路径名
    read从 STDIN 读取一行数据并将其赋给一个变量
    readarray从 STDIN 读取数据行并将其放入索引数组
    readonly从 STDIN 读取一行数据并将其赋给一个不可修改的变量
    return强制函数以某个值退出,这个值可以被调用脚本提取
    set设置并显示环境变量的值和 shell 属性
    shift将位置参数依次向下降一个位置
    shopt打开/关闭控制 shell 可选行为的变量值
    source读取并执行指定文件中的命令(在当前 shell 环境中)
    suspend暂停 Shell 的执行,直到收到一个 SIGCONT 信号
    test基于指定条件返回退出状态码 0 或 1
    times显示累计的用户和系统时间
    trap如果收到了指定的系统信号,执行指定的命令
    type显示指定的单词如果作为命令将会如何被解释
    typeset声明一个变量或变量类型。
    ulimit为系统用户设置指定的资源的上限
    umask为新建的文件和目录设置默认权限
    unalias刪除指定的别名
    unset刪除指定的环境变量或 shell 属性
    wait等待指定的进程完成,并返回退出状态码

    alias:给命令创建别名

    alisa 用来给命令创建一个别名。若直接输入该命令且不带任何参数,则列出当前 Shell 进程中使用了哪些别名。

    使用 alias 命令自定义别名

    语法格式为:alias new_name='command'

    别名只是临时的

    在代码中使用 alias 命令定义的别名只能在当前 Shell 进程中使用,在子进程和其它进程中都不能使用。当前 Shell 进程结束后,别名也随之消失。

    要想让别名对所有的 Shell 进程都有效,就得把别名写入 Shell 配置文件。Shell 进程每次启动时都会执行配置文件中的代码做一些初始化工作,将别名放在配置文件中,那么每次启动进程都会定义这个别名。

    使用 unalias 命令删除别名 

    使用 unalias 内建命令可以删除当前 Shell 进程中的别名。unalias 有两种使用方法:

    • 第一种用法是在命令后跟上某个命令的别名,用于删除指定的别名。
    • 第二种用法是在命令后接-a参数,删除当前 Shell 进程中所有的别名。

    同样,这两种方法都是在当前 Shell 进程中生效的。要想永久删除配置文件中定义的别名,只能进入该文件手动删除。 

     echo命令

     echo 是一个Shell内置命令,用来在终端输出字符串,并在最后默认加上换行符。

    1、显示普通字符串: echo "It is a test"   双引号可省略

    2、显示转义字符:echo "\"It is a test\""     双引号可省略

    3、显示变量:echo "$name It is a test"

    4、显示换行:-e 开启转义

    5、显示不换行:echo 命令输出结束后默认会换行,如果不希望换行,可以加上-n参数

    6、显示结果定向至文件:echo "It is a test" > myfile

    7、原样输出字符串,不进行转义或取变量(用单引号):echo '$name\"'

    8、显示命令执行结果:echo `date`

    read命令:读取从键盘输入的数据

     read 是Shell内置命令,用来从标准输入中读取数据并赋值给变量。如果没有进行重定向,默认就是从键盘读取用户输入的数据;如果进行了重定向,那么可以从文件中读取数据

    read 命令的用法为:read [-options] [variables]

    options表示选项,如下表所示;variables表示用来存储数据的变量,可以有一个,也可以有多个。
    optionsvariables都是可选的,如果没有提供变量名,那么读取的数据将存放到环境变量 REPLY 中。 

    Shell read 命令支持的选项
    选项说明
    -a array把读取的数据赋值给数组 array,从下标 0 开始。
    -d delimiter用字符串 delimiter 指定读取结束的位置,而不是一个换行符(读取到的数据不包括 delimiter)。
    -e在获取用户输入的时候,对功能键进行编码转换,不会直接显式功能键对应的字符。
    -n num读取 num 个字符,而不是整行字符。
    -p prompt显示提示信息,提示内容为 prompt。
    -r原样读取(Raw mode),不把反斜杠字符解释为转义字符。
    -s静默模式(Silent mode),不会在屏幕上显示输入的字符。当输入密码和其它确认信息的时候,这是很有必要的。
    -t seconds设置超时时间,单位为秒。如果用户没有在指定时间内输入完成,那么 read 将会返回一个非 0 的退出状态,表示读取失败。
    -u fd使用文件描述符 fd 作为输入源,而不是标准输入,类似于重定向。

    【实例1】使用 read 命令给多个变量赋值。

    1. #!/bin/bash
    2. read -p "Enter some information > " name url age
    3. echo "网站名字:$name"
    4. echo "网址:$url"
    5. echo "年龄:$age"

    注意,必须在一行内输入所有的值,不能换行,否则只能给第一个变量赋值,后续变量都会赋值失败。

    本例还使用了-p选项,该选项会用一段文本来提示用户输入。

      

    【示例2】只读取一个字符

    1. #!/bin/bash
    2. read -n 1 -p "Enter a char > " char
    3. printf "\n" #换行
    4. echo $char

    -n 1表示只读取一个字符。运行脚本后,只要用户输入一个字符,立即读取结束,不用等待用户按下回车键。

     printf "\n"语句用来达到换行的效果,否则 echo 的输出结果会和用户输入的内容位于同一行,不容易区分。
     

    【实例3】在指定时间内输入密码。

    1. #!/bin/bash
    2. if
    3. read -t 20 -sp "Enter password in 20 seconds(once) > " pass1 && printf "\n" && #第一次输入密码
    4. read -t 20 -sp "Enter password in 20 seconds(again)> " pass2 && printf "\n" && #第二次输入密码
    5. [ $pass1 == $pass2 ] #判断两次输入的密码是否相等
    6. then
    7. echo "Valid password"
    8. else
    9. echo "Invalid password"
    10. fi

    这段代码中,我们使用&&组合了多个命令,这些命令会依次执行,并且从整体上作为 if 语句的判断条件,只要其中一个命令执行失败(退出状态为非 0 值),整个判断条件就失败了,后续的命令也就没有必要执行了。

    printf 命令 

    printf 命令模仿 C 程序库(library)里的 printf() 程序。

    printf 由 POSIX 标准所定义,因此使用 printf 的脚本比使用 echo 移植性好。

    printf 使用引用文本或空格分隔的参数,外面可以在 printf 中使用格式化字符串,还可以制定字符串的宽度、左右对齐方式等。默认的 printf 不会像 echo 自动添加换行符,我们可以手动添加 \n。

    printf 命令的语法:

    printf  format-string  [arguments...]

    参数说明:

    • format-string: 为格式控制字符串
    • arguments: 为参数列表。

     printf 的转义序列

    序列说明
    \a警告字符,通常为ASCII的BEL字符
    \b后退
    \c抑制(不显示)输出结果中任何结尾的换行字符(只在%b格式指示符控制下的参数字符串中有效),而且,任何留在参数里的字符、任何接下来的参数以及任何留在格式字符串中的字符,都被忽略
    \f换页(formfeed)
    \n换行
    \r回车(Carriage return)
    \t水平制表符
    \v垂直制表符
    \\一个字面上的反斜杠字符
    \ddd表示1到3位数八进制值的字符。仅在格式字符串中有效
    \0ddd表示1到3位的八进制值字符
    1. #!/bin/bash
    2. # author:菜鸟教程
    3. # url:www.runoob.com
    4. printf "%-10s %-8s %-4s\n" 姓名 性别 体重kg
    5. printf "%-10s %-8s %-4.2f\n" 郭靖 男 66.1234
    6. printf "%-10s %-8s %-4.2f\n" 杨过 男 48.6543
    7. printf "%-10s %-8s %-4.2f\n" 郭芙 女 47.9876

     %s %c %d %f 都是格式替代符,%s 输出一个字符串,%d 整型输出,%c 输出一个字符,%f 输出实数,以小数形式输出。

    %-10s 指一个宽度为 10 个字符(- 表示左对齐,没有则表示右对齐),任何字符都会被显示在 10 个字符宽的字符内,如果不足则自动以空格填充,超过也会将内容全部显示出来。

    %-4.2f 指格式化为小数,其中 .2 指保留2位小数。

    test 命令 

    Shell中的 test 命令用于检查某个条件是否成立,它可以进行数值、字符和文件三个方面的测试。 

    数值测试

    参数说明
    -eq等于则为真
    -ne不等于则为真
    -gt大于则为真
    -ge大于等于则为真
    -lt小于则为真
    -le小于等于则为真

    代码中的 [] 执行基本的算数运算

    1. num1=100
    2. num2=100
    3. result=$[num1+num2] # 注意等号两边不能有空格
    4. if test $[num1] -eq $[num2]
    5. then
    6. echo '两个数相等!'
    7. else
    8. echo '两个数不相等!'
    9. fi

    字符串测试

    参数说明
    =等于则为真
    !=不相等则为真
    -z 字符串字符串的长度为零则为真
    -n 字符串字符串的长度不为零则为真

     文件测试

    参数说明
    -e 文件名如果文件存在则为真
    -r 文件名如果文件存在且可读则为真
    -w 文件名如果文件存在且可写则为真
    -x 文件名如果文件存在且可执行则为真
    -s 文件名如果文件存在且至少有一个字符则为真
    -d 文件名如果文件存在且为目录则为真
    -f 文件名如果文件存在且为普通文件则为真
    -c 文件名如果文件存在且为字符型特殊文件则为真
    -b 文件名如果文件存在且为块特殊文件则为真

     另外,Shell 还提供了与( -a )、或( -o )、非( ! )三个逻辑操作符用于将测试条件连接起来,其优先级为: ! 最高, -a 次之, -o 最低。例如:

    1. cd /bin
    2. if test -e ./notFile -o -e ./bash
    3. then
    4.     echo '至少有一个文件存在!'
    5. else
    6.     echo '两个文件都不存在'
    7. fi

    exit命令:退出当前进程

    exit 是一个Shell内置命令,用来退出当前 Shell 进程,并返回一个退出状态;使用$?可以接收这个退出状态 

    exit 命令可以接受一个整数值作为参数,代表退出状态。如果不指定,默认状态值是 0。

    一般情况下,退出状态为 0 表示成功,退出状态为非 0 表示执行失败(出错)了。

    exit 退出状态只能是一个介于 0~255 之间的整数,其中只有 0 表示成功,其它值都表示失败。

    Shell退出状态

    每一条 Shell 命令,不管是 Bash 内置命令(例如 cd、echo),还是外部的 Linux 命令(例如 ls、awk),还是自定义的 Shell 函数,当它退出(运行结束)时,都会返回一个比较小的整数值给调用(使用)它的程序,这就是命令的退出状态(exit statu)

    按照惯例来说,退出状态为 0 表示“成功”;也就是说,程序执行完成并且没有遇到任何问题。除 0 以外的其它任何退出状态都为“失败”。

    之所以说这是“惯例”而非“规定”,是因为也会有例外,比如 diff 命令用来比较两个文件的不同,对于“没有差别”的文件返回 0,对于“找到差别”的文件返回 1,对无效文件名返回 2。

    退出状态和逻辑运算符的组合

    Shell if 语句的一个神奇之处是允许我们使用逻辑运算符将多个退出状态组合起来,这样就可以一次判断多个条件了。

    Shell 逻辑运算符
    运算符使用格式说明
    &&expression1 && expression2逻辑与运算符,当 expression1 和 expression2 同时成立时,整个表达式才成立。

    如果检测到 expression1 的退出状态为 0,就不会再检测 expression2 了,因为不管 expression2 的退出状态是什么,整个表达式必然都是不成立的,检测了也是多此一举。
    ||expression1 || expression2逻辑或运算符,expression1 和 expression2 两个表达式中只要有一个成立,整个表达式就成立。

    如果检测到 expression1 的退出状态为 1,就不会再检测 expression2 了,因为不管 expression2 的退出状态是什么,整个表达式必然都是成立的,检测了也是多此一举。
    !!expression逻辑非运算符,相当于“取反”的效果。如果 expression 成立,那么整个表达式就不成立;如果 expression 不成立,那么整个表达式就成立。

    declare和typeset命令:设置变量属性

    declare 和 typeset 都是 Shell 内建命令,它们的用法相同,都用来设置变量的属性。不过 typeset 已经被弃用了,建议使用 declare 代替。

    declare 命令的用法如下所示:

    declare [+/-] [aAfFgilprtux] [变量名=变量值]

    其中,-表示设置属性,+表示取消属性,aAfFgilprtux都是具体的选项,它们的含义如下表所示:

    选项含义
    -f [name]列出之前由用户在脚本中定义的函数名称和函数体。
    -F [name]仅列出自定义函数名称。
    -g name在 Shell 函数内部创建全局变量。
    -p [name]显示指定变量的属性和值。
    -a name声明变量为普通数组。
    -A name声明变量为关联数组(支持索引下标为字符串)。
    -i name 将变量定义为整数型。
    -r name[=value] 将变量定义为只读(不可修改和删除),等价于 readonly name。
    -x name[=value]将变量设置为环境变量,等价于 export name[=value]。
  • 相关阅读:
    LeetCode 0086.分隔链表
    如何给Github上的开源项目提交PR?
    挑战来了!如何应对大商家订单多小商家没有订单的数据倾斜问题?
    window安装rust
    npm与Maven:前端与后端构建工具深度对比学习
    如何把A3 pdf 文章打印成A4
    java开放式实验室预约系统计算机毕业设计MyBatis+系统+LW文档+源码+调试部署
    vue的组件使用
    xxl-job做集群的时候,用F5做负载均衡效率高还是直接写死几个服务器地址的效率高?
    Nginx入门到搭建
  • 原文地址:https://blog.csdn.net/weixin_47203903/article/details/128125914