Skip to content

2-1.数据类型

所有编程语言,都应该从区分数据类型开始。

shell的数据类型有下面几种:

  • 字符串

    shell
      name='jack'
  • 整数型 shell 中的数字都是整数。不能声明变量是小数。

    shell
      num=19
  • 数组 shell 支持一维数组(不支持多维数组),并且没有限定数组的大小。用括号来表示数组,数组元素用空格符号分割开。

    数组的话,分为两类:普通数组关联数组

    普通数组是直接利用声明语句声明即可,无法自定义索引值。

    关联数组则可以自定义索引值。

    所有语法如下:

    shell
    #!/bin/bash
    #普通数组直接声明即可。
    arr=('v1' 'v2' 'v3')
    
    #下述所有方法 普通数组与关联数组的使用方式是一致的。
    #读取对应索引下的值 索引从0开始
    echo ${arr[0]}
    #读取全部索引下的值
    echo ${arr[*]}
    echo ${arr[@]}
    #获取指定索引后的所有值 获取从索引1开始的值,如下:
    echo ${arr[*]:1}
    echo ${arr[@]:1}
    #获取指定索引后的固定个数的值 获取从索引1开始的3个值,如下:
    echo ${arr[*]:1:3}
    echo ${arr[@]:1:3}
    #获取全部索引
    echo ${!arr[*]}
    echo ${!arr[@]}
    #获取数组长度
    echo ${#arr[*]}
    echo ${#arr[@]}
    #列出当前环境下的所有数组
    declare -a

    不管是普通数组,还是关联数组,如果读取时没有指定索引,统一会取第一位索引的值。这一点与 JavaScript 语言有明显区别:

    shell
    arr=('v1' 'v2' 'v3')
    #不会打印出'v1 v2 v3' 只会打印出'v1'
    echo ${arr}
    #说明这一点的原因是 在使用for语句循环时 应该遍历的是${arr[*]} 而不是${arr}

    如果想要声明关联数组,需要使用 declare -A 语法。如下:

    shell
    #!/bin/bash
    #1.声明单个索引
    #这里如果不加这一行 declare -A的话,会报错 'assignment to invalid subscript range'.
    declare -A arr_1
    arr_1[name]='jack'
    arr_1[gender]='male'
    echo ${arr_1[name]}
    #2.声明整个数组
    declare -A arr_2=(name='selina' gender='female')
    echo ${arr_2[name]}

    TIP

    macos 上使用 declare -A,有可能报错:

    declare: -A: invalid option

    declare: usage: declare [-afFirtx] [-p] [name[=value] ...]

    这是因为 bash 的版本问题,可以升级下版本或者使用 zsh 等。

    可见stackoverflow

2-2.自定义变量

声明自定义变量,直接使用赋值语句即可。

使用自定义变量,需要加 $ 进行读取。

shell
a='123'

a=123
#打印出来的都是字符串123 shell中没有数字的概念
echo $a
#更加友好的读取变量方式 推荐使用:
echo ${a}

删除自定义变量的话,可以使用:

name='jack'
unset name

2-3..sh 文件

一般,我们都会将 shell 命令放到 .sh 文件中。

需要现在文件头部声明使用什么样的 shell,譬如:

shell
#!/bin/bash
echo $PATH

#!/bin/bash 即使用 bash,当然也可以声明其他的 shell

如果你在 .sh 文件内,想要使用注释的话,使用 # 即可。

shell
#!/bin/bash

#这是一行注释
echo $PATH

2-4.文件执行

shell 命令都会存在于以 .sh 为后缀的文件中。

执行 sh 文件有两种方式(假设当前目录下文件名为 test.sh):

  • ./test.sh

    这种方式,需要 sh 文件具有可执行权限。查看文件所有权限可利用 ls -l。如果没有执行权限的话,可利用 chmod +x test.sh 来给文件添加可执行权限。

  • sh test.sh

    这种方式,无需 sh 文件具有可执行权限。因为这种方式,已经表明了利用 shell 来执行 test.sh。除此命令外,也可以使用 bash test.sh 或者 zsh test.sh 等等。

    使用这种方式的话,可以不在 .sh 文件头部添加声明语句 #!/bin/bash。因为这种执行方式已经具体定义了使用哪种的 shell

2-5.参数变量

在执行 sh 文件时,可以在指令后面添加一些参数。

shell 内部能够通过对应变量来读取这些参数:

shell
#!/bin/bash

#假设执行命令为 'sh test.sh jack'

#参数变量的总数量 因为参数只有一个jack 所以打印 '1'
echo $#

#运行的脚本名称 打印 'test.sh'
echo $0

#第一个参数变量,$2、$3...以此类推,不存在的话打印空字符串,此处打印 'jack'
echo $1

2-6.特殊符号

  • ~ 家目录。可使用 cd ~,快速进入家目录。

  • - 上一次的目录。可使用 cd -1 或者 cd -,回退到上次目录。

  • ! 执行历史命令。!! 执行上次命令。可利用 history 查看历史命令列表。

  • $ 读取变量。

  • * 通配符,匹配所有字符。如果需要使用乘法 *,需要利用转义字符 \ 将其转义。

  • ? 通配符,匹配除回车外的一个字符。

  • ; 命令之间用分号分割,多个命令在一行中时 可添加分号执行。

  • | 管道符,上一个命令的输出作为下一个命令的输入。cat filename | grep "abc"

  • \ 转义字符。

  • + 数学运算中的加法。

  • - 数学运算中的减法。

  • * 数学运算中的乘法。

  • / 数学运算中的除法。

  • % 数学运算中的取余。

  • ** 数学运算中的乘方。

  • shell 内的引号分为 3 种:

    • 双引号 ""

      双引号,它相对宽松。会区分特殊字符:美元符号 $、反斜杠 \ 和反引号 ``。

    • 单引号 ''

      单引号,可以认作严格模式。它不会区分特殊符号,统一作字符串处理。

    • 反引号 ``

      要求 shell 执行被它括起来的内容,例如执行 echo pwd,相当于直接执行 pwd 命令。

2-7.数学运算

数学运算有3中方法:

  • expr
    shell
    #!/bin/bash
    
    #注意这里需要有空格,不能写成 expr 1+2
    expr 1 + 2
  • let
    shell
    a=1
    b=2
    let "c = ${a} + ${b}"
  • $(())
    shell
    echo $((1 + 2))

注意,上述运算的小数运算有问题。可以安装第三方库 bc 进行支持。

TIP

Macos 下的包管理器是 brew,即 HomeBrew

CentosRedhat 下的包管理器是 yum

UbuntuDebian 下的包管理器是 apt-get

2-8.格式化输出

相对于浏览器中的 console.logshell 中的打印输出对应的是 echo 命令。

可利用 man echo 查看该命令对应的配置。

基本语法如下:

echo(选项)(参数)

选项

  • -n 文本输出不换行。默认的 echo 在输出时末尾会自带一个换行符。
  • -e 激活转义字符。使用 -e 选项时,若字符串中出现以下字符,则特别加以处理,而不会将它当成一般文字输出:
    • \a 发出警告声;
    • \b 删除前一个字符;
    • \c 删除后面的字符,\c 后面的字符不会输出;
    • \f 换行但光标仍旧停留在原来的位置;
    • \n 换行且光标移至行首;
    • \r 光标移至行首,但不换行;
    • \t 插入tab;
    • \v\f 相同;
    • \\ 插入 \ 字符;
    • \nnn 插入 nnn(八进制)所代表的 ASCII 字符。

定制化文本

echo -e "\033[字背景颜色;文字颜色m字符串\033[0m"
  • 文字颜色 数值:30 - 37

    shell
      echo -e "\033[30m 黑色字 \033[0m" 
      echo -e "\033[31m 红色字 \033[0m" 
      echo -e "\033[32m 绿色字 \033[0m" 
      echo -e "\033[33m 黄色字 \033[0m" 
      echo -e "\033[34m 蓝色字 \033[0m" 
      echo -e "\033[35m 紫色字 \033[0m" 
      echo -e "\033[36m 天蓝字 \033[0m" 
      echo -e "\033[37m 白色字 \033[0m"
  • 背景色 数值:40 - 47

    shell
      echo -e "\033[40;37m 黑底白字 \033[0m" 
      echo -e "\033[41;37m 红底白字 \033[0m" 
      echo -e "\033[42;37m 绿底白字 \033[0m" 
      echo -e "\033[43;37m 黄底白字 \033[0m" 
      echo -e "\033[44;37m 蓝底白字 \033[0m" 
      echo -e "\033[45;37m 紫底白字 \033[0m" 
      echo -e "\033[46;37m 天蓝底白字 \033[0m" 
      echo -e "\033[47;30m 白底黑字 \033[0m"
  • 文字闪动

      \33[0m 关闭所有属性 
      \33[1m 设置高亮度 
      \33[4m 下划线 
      \33[5m 闪烁 
      \33[7m 反显 
      \33[8m 消隐 
      \33[30m — \33[37m 设置前景色 
      \33[40m — \33[47m 设置背景色 
      \33[nA 光标上移n行 
      \33[nB 光标下移n行 
      \33[nC 光标右移n行 
      \33[nD 光标左移n行 
      \33[y;xH设置光标位置 
      \33[2J 清屏 
      \33[K 清除从光标到行尾的内容 
      \33[s 保存光标位置 
      \33[u 恢复光标位置 
      \33[?25l 隐藏光标 
      \33[?25h 显示光标

2-9.用户交互

在实际应用中,我们可能会与用户进行交互,需要用户输入一些值。这时就要使用 read 命令。

shell
#!/bin/bash
read name
echo ${name}

直接这样使用,对用户不太友好。所以我们可以使用 -p 选项来对用户展示提示信息。prompt 的简写。

shell
#!/bin/bash
read -p "请输入您的姓名:" name
echo ${name}

除此之外,还有更多的选项可供使用:

  • -n 后跟一个数字,定义输入文本的长度。
  • -s 在输入时不在屏幕上显示,例如输入密码时。
  • -t 后面跟秒数,定义输入字符的等待时间。