[关闭]
@Chiang 2020-02-02T13:18:45.000000Z 字数 6547 阅读 477

shell变量

Linux Shell


与其他高级语言一样,Shell 支持自定义变量。Shell 的变量类型有两种,即 Shell 环境变量(Shell Enviroment Variable)和用户自定义变量(User Define Variable)。

Shell 的环境变量

Shell 环境变量的作用是定制 Shell 的运行环境,并保证 Shell 命令的正确执行。它又分为可写和只读两大类。

可写的环境变量

可写的环境变量可以对其进行赋值操作,大部分可写的 shell 环境变量都在登录过程中执行 “/etc/profile” 文件时进行初始化。该文件在用户登录时,被系统自动执行,为所有用户设置公共的工作环境。用户也可以通过修改自己主目录下的 .profile 或 .bash_profile 中的部分变量值来定制自己的运行环境。以下列出部分可写的环境变量:

  • BASH 展开为调用bash实例时使用的全路径名
  • CDPATH cd命令的搜索路径。它是以冒号分隔的目录列表,shell通过它来搜索cd命令指定的目标目录。
  • EDITOR 内置编辑器emacs、gmacs或vi的路径名
  • ENV 每一个新的bash shell(包括脚本)启动时执行的环境文件。通常赋予这个变量的文件名是.bashrc。
  • EUID 展开为在shell启动时被初始化的当前用户的有效ID
  • GROUPS 当前用户所属的组
  • HISTFIL E 指定保存命令行历史的文件。默认值是~/.bash_history。如果被复位,交互式shell退出时将不保存命令行历史
  • HISTSIZE 记录在命令行历史文件中的命令数。默认是500
  • HOME 主目录。未指定目录时,cd命令将转向该目录
  • IFS 内部字段分隔符,一般是空格符、制表符和换行符,用于由命令替换,循环结构中的表和读取的输入产生的词的字段划分
  • LANG 用来为没有以LC_开头的变量明确选取的种类确定locale类
  • OLDPWD 前一个工作目录
  • PATH 命令搜索路径。一个由冒号分隔的目录列表,shell用它来搜索命令。
  • LD_LIBRARY_PATH 库文件搜索路径。在执行程序是会自动到该变量设置的路径下搜索库文件。
  • PPID 父进程的进程ID
  • PS1 主提示符串,默认值是$
  • PS2 次提示符串,默认值是>
  • PS3 与select命令一起使用的选择提示符串,默认值是#?
  • PS4 当开启追踪时使用的调试提示符串,默认值是+。追踪可以用set –x开启
  • PWD 当前工作目录。由cd设置
  • RANDOM 每次引用该变量,就产生一个随机整数。随机数序列可以通过给RANDOM赋值来初始化。如果RANDOM被复位,即使随后再设置,它也将失去特定的属性
  • REPLY 当没有给read提供参数时设置
  • SHEL L 当调用shell时,它扫描环境变量以寻找该名字。shell给PATH、PS1、PS2、MAILCHECK和IFS设置默认值。HOME和MAIL由login(1)设置
  • SHELLOPTS 包含一列开启的shell选项,比如braceexpand、hashall、monitor等
  • UID 展开为当前用户的用户ID,在shell启动时初始化

这里重点讲解一下 PATH 和 LD_LIBRARY_PATH 环境变量,这两个变量是在我的工作经历中用得最多的,如果在 Linux 下进行工作,就不可避免的会用到这两个变量。其他变量也并非不重要,有的使用频率也很高,只是相对来说 PATH 和 LD_LIBRARY_PATH 的实用性很强。 PATH 用于保存可执行文件的搜索路径,在该变量中的目录下的可执行程序可以直接执行。 LD_LIBRARY_PATH 用于保存库文件的搜索路径,在 Linux 中通常把很多程序都会用到的通用的库文件方法一些固定的目录下,程序运行时再到这些目录中去搜索加载库文件。在工作,我通常需要编译统一软件的多个版本,并且同时放到系统中运行。这个时候,如果将多个版本都直接安装到系统指定的目录中,则会引起混乱,或者覆盖之前的版本。所以 PATH 和 LD_LIBRARY_PATH 环境变量就起到了作用,你可以将不同的版本安装到不同的目录下,然后将它们的可执行文件路径和库文件路径添加到 PATH 和 LD_LIBRARY_PATH 变量中。在做嵌入式的开发中,配置交叉编译工具时,也会用到这两个变量。

环境变量一般都是大写的,系统启动后自动加载,可写的环境变量用户也可以随时进行修改。查看环境变量时,可以在变量名前加上美元符号 $ ,然后再用 echo 打印, 例如:

  1. echo $PS1

输出结果:

[\033[01;32m]\u[\033[01;31m]$[\033[01;36m][\W][\033[01;32m] ->[\033[00m]

这是我的终端提示符样式,我在 ~/.bashrc 文件中对其进行了设置。

只读的环境变量

只读的 Shell 环境变量意味着用户能使用和读取它们的值,而不能对他们进行修改。只读的 Shell 环境变量有两种:一种是特殊的环境变量,另一种是位置参数。

特殊环境变量

特殊的环境变量是系统预先定义好的,用户不能重新设置,常见的只读环境变量如下所示:

  • num:num为从1开始的数字, 2是第二个参数,
  • #:传入脚本的参数的个数
    >*
    *:所有的位置参数(作为单个字符串)
  • ?:当前shell进程中,上一个命令的返回值,如果上一个命令成功执行则!:后台运行的最后一个进程的pid
  • 使_:之前命令的最后一个参数

位置参数

用于处理命令行参数(Command Lines Argument),出现在命令行上的位置确定的参数称作位置参数(Positon Argument),也就是在命令行传递给 Shell 脚本的参数。

在 Bash 中总共有十个位置参数,其对应的名称一次是 1, 3, 5, 7, 9。其中 0;而其他位置参数依据实际需求,可有可无。

输出位置参数:

可以用 echo 命令输出位置参数。如下例所示:

  1. #!/bin/bash
  2. # Filename: test2-1.sh
  3. # Author: huoty <sudohuoty@163.com>
  4. # Script starts from here:
  5. echo $1 $2 $3 $4 $5 $6 $7 $8 $9 $0

执行该脚本:

  1. sh test2-1.sh a b c d e f g

输出:

a b c d e f g test2-1.sh

用 set 命令给位置参数赋值

除了 $0 不能用 set 赋值外,其他位置参数都能用 set 对其手动赋值。示例:

  1. #!/bin/bash
  2. # Filename: test2-2.sh
  3. # Author: huoty <sudohuoty@163.com>
  4. # Script starts from here:
  5. echo $1 $2 $3
  6. set m1 m2 m3
  7. echo $1 $2 $3

运行脚本:

  1. sh test2-2.sh a1 a2 a3

输出:

a1 a2 a3
m1 m2 m3

移动位置参数(shift)

在 Shell 中规定,位置参数最多不能超过 9 个,即 9。如果实际给定的命令行参数多于 9 个,就需要用 shift 命令移动位置参数。执行一次 shift 命令,就把诶之参数整体向左移一位,即原来 1 的值是原来 2 的值是原来 0 移走,所以经 shitf 左移参数后, 0 的值。Shift 命令可以带有一个整数作为参数,该参数表示一次左移的位数,若果未带参数,则默认值为1。如下示例所示:

  1. #!/bin/bash
  2. # Filename: test2-3.sh
  3. # Author: huoty <sudohuoty@163.com>
  4. # Script starts from here:
  5. echo $0 $1 $2 $3 $4 $5 $6 $7 $8 $9 $#
  6. shift
  7. echo $0 $1 $2 $3 $4 $5 $6 $7 $8 $9 $#
  8. shift 5
  9. echo $0 $1 $2 $3 $4 $5 $6 $7 $8 $9 $#

执行脚本:

  1. sh test2-3.sh a b c d f g h i j k

输出结果:

test2-3.sh a b c d f g h i j 10
test2-3.sh b c d f g h i j k 9
test2-3.sh h i j k 4

Shell 的用户自定义变量

Shell 编程中允许用户自定义变量,变量拥有临时的存储空间,在程序执行过程中其值可以改变,这些变量可以被设置为只读,也可以传递给定义他们的 Shell 脚本中的命令。Shell 中的变量无需声明和初始化,一个未初始化的 Shell 变量,其默认的初始化值为空字符串。

用户自定义变量的命名只要是合法的标识符即可,且区分大小写,变量名的长度不受限制。定义变量名并赋值的形式有以下几种:

字符串赋值,其格式为:

  1. 变量名=字符串

例如: mydir=/home/a ,其中,“mydir”是变量名,“=”是赋值符号,字符串“/home/a”是赋予的值。变量的值可以改变,只需利用赋值语句重新给它赋值即可。 注意: 再赋值语句中,赋值符号的两边没有空格,否则在执行时会引起错误。

在程序中,变量的使用方式是再变量名前加上符号 $ 。该符号告诉 Shell 要取出其后变量的值。示例:

  1. $ mydir=/home/a
  2. $ echo $mydir
  3. mydir=/home/a
  4. $ echo mydir
  5. mydir

以上演示结果显示,如果不加 $ 就无法引用变量的值。

如果在赋值给变量的值中含有空格、制表符或者换行符,那么就应该用双引号把这个字符串括起来。例如:myname=”Huoty Kong”,如果没有用引号括起来,则 myname 的值就是 Huoty。

变量值可以作为某个长字符串中的一部分,如果它在长字符串的末尾,就可以利用直接引用形式。变量名出现在一个长字符串的开头或者中间,应该用 "{}" 把变量名括起来。示例:

  1. #!/bin/bash
  2. # Filename: test2-1.sh
  3. # Author: huoty <sudohuoty@163.com>
  4. # Script starts from here:
  5. s1=ing
  6. echo walk$s1 or read$s1 or sleep$s1
  7. dir=/home/huoty/
  8. echo ${dir}m1.c

使用不带参数的 set 命令可以显示可以显示所有 Shell 变量(包括环境变量和用户自定义变量)名以及它们的当前值。Set 命令也可以用于改变一些只读 Shell 环境变量的值。对用户自定义变量使用 readonly 命令,可以将变量定义为只读变量,只读变量的值不能被改变。定义好的变量也可以使用 unset 命令进行删除。示例:

  1. #!/bin/bash
  2. # Filename: test2-1.sh
  3. # Author: huoty <sudohuoty@163.com>
  4. # Script starts from here:
  5. myEmail="huoty@gmail.com"
  6. echo $myEmail
  7. unset myEmail
  8. echo $myEmail
  9. myUrl="http://kuanghy.github.io/"
  10. echo $myUrl
  11. readonly myUrl
  12. myUrl="http://kuanghy.github.io/kswd"

运行时会出现如下错误:

test2-5.sh: 15: test2-5.sh: myUrl: is read only

Shell 的变量扩展功能

Shell 中有一些变量扩展的技巧,可以很方便的处理变量。

截取字符串

Shell 从变量中取子字符串的规则如下:

  1. ${变量名:位置起点} ${变量名:位置起点:长度}

示例:

  1. var="12345678"
  2. echo ${var:5}
  3. echo${var:0:5}

执行脚本输出结果为:

678
12345

计算字符串长度

在 Shell 中可以计算字符串的长度,其规则为:

  1. ${#变量名称}

示例:

  1. var="12345678"
  2. echo ${#var} # 输出:8

对比样式

规则1

  1. 规则1${变量#样式}

含义: 表示由变量值的最左边开始与样式进行对比,删除”最短相符合的字符串”

例1:

  1. var="12345678"
  2. echo ${var#*3} #输出:45678

规则2

  1. 规则2${变量##样式}

含义: 表示由变量值的最左边开始与样式进行对比,删除”最长相符合的字符串”

例2:

  1. var="12341234"
  2. echo ${var##*3} # 输出:4

规则3

  1. 规则3${变量%样式}

含义: 表示由变量值的最右边或最后边开始与样式进行对比,删除”最短相符的字符串”

例3:

  1. var="12341234"
  2. echo ${var%3*} # 输出:123412

规则4

  1. 规则4${变量%%样式}

含义: 表示由变量值的最右边或最后边开始与样式进行对比,删除”最长相符的字符串”

例4:

  1. var="12341234"
  2. echo ${var%%3*} # 输出:12

替换或者删除部分字符串

规则1

  1. 规则1${变量/样式/替换字符串}

含义: 如果变量中有符合样式的字符串,则使用替换字符串替代,只替换第一个符合样式的字符串

例1:

  1. var="12341234"
  2. echo ${var/1234/1111} # 输出:11111234

规则2

  1. 规则2${变量//样式/替换字符串}

含义: 如果变量中有符合样式的字符串,则使用替换字符串替代,替换全部符合样式的字符串

例1

  1. var="12341234"
  2. echo ${var//123/} # 输出:44

Shell 定义数组

Bash 支持一维数组(不支持多维数组),并且没有限定数组的大小,数组元素的下标由0开始编号。获取数组中的元素要利用下标,下标可以是整数或算术表达式,其值应大于或等于0。 在 Shell 中,用括号来表示数组,数组元素用“空格”符号分割开。定义数组的一般形式为:

  1. array_name=(value0 value1 value2 valuen)

也可以单独定义数组的各个分量:

  1. array_name[0]=value0
  2. array_name[1]=value1
  3. array_name[2]=value2
  4. ...
  5. array_name[n]=valuen

读取数组元素值的一般格式是:

  1. ${array_name[index]}

使用@ 或 * 可以获取数组中的所有元素,示例:

  1. #!/bin/sh
  2. NAME[0]="Zara"
  3. NAME[1]="Qadir"
  4. NAME[2]="Mahnaz"
  5. NAME[3]="Ayan"
  6. NAME[4]="Daisy"
  7. echo "First Index: ${NAME[0]}"
  8. echo "Second Index: ${NAME[1]}"
  9. echo "First Method: ${NAME[*]}"
  10. echo "Second Method: ${NAME[@]}"

获取数组长度的方法与获取字符串长度的方法相同,例如:

  1. # 取得数组元素的个数
  2. length=${#array_name[@]}
  3. # 或者
  4. length=${#array_name[*]}
  5. # 取得数组单个元素的长度
  6. lengthn=${#array_name[n]}

参考资料:
Shell 程序设计教程

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注