Bash脚本教程之变量

举报
孙叫兽 发表于 2021/03/28 03:33:04 2021/03/28
【摘要】 目录 简介 创建变量 读取变量 删除变量 输出变量,export 命令 特殊变量 变量的默认值 declare 命令 readonly 命令 let 命令 Bash 变量分成环境变量和自定义变量两类。 简介 环境变量是 Bash 环境自带的变量,进入 Shell 时已经定义好了,可以直接使用。它们通常是系统定义好的,也可以由用户从父 Shell 传...

目录

简介

创建变量

读取变量

删除变量

输出变量,export 命令

特殊变量

变量的默认值

declare 命令

readonly 命令

let 命令


Bash 变量分成环境变量和自定义变量两类。

简介

环境变量是 Bash 环境自带的变量,进入 Shell 时已经定义好了,可以直接使用。它们通常是系统定义好的,也可以由用户从父 Shell 传入子 Shell。

env命令或printenv命令,可以显示所有环境变量。


  
  1. $ env
  2. # 或者
  3. $ printenv

下面是一些常见的环境变量。

  • BASHPID:Bash 进程的进程 ID。
  • BASHOPTS:当前 Shell 的参数,可以用shopt命令修改。
  • DISPLAY:图形环境的显示器名字,通常是:0,表示 X Server 的第一个显示器。
  • EDITOR:默认的文本编辑器。
  • HOME:用户的主目录。
  • HOST:当前主机的名称。
  • IFS:词与词之间的分隔符,默认为空格。
  • LANG:字符集以及语言编码,比如zh_CN.UTF-8
  • PATH:由冒号分开的目录列表,当输入可执行程序名后,会搜索这个目录列表。
  • PS1:Shell 提示符。
  • PS2: 输入多行命令时,次要的 Shell 提示符。
  • PWD:当前工作目录。
  • RANDOM:返回一个0到32767之间的随机数。
  • SHELL:Shell 的名字。
  • SHELLOPTS:启动当前 Shell 的set命令的参数,参见《set 命令》一章。
  • TERM:终端类型名,即终端仿真器所用的协议。
  • UID:当前用户的 ID 编号。
  • USER:当前用户的用户名。

很多环境变量很少发生变化,而且是只读的,可以视为常量。由于它们的变量名全部都是大写,所以传统上,如果用户要自己定义一个常量,也会使用全部大写的变量名。

注意,Bash 变量名区分大小写,HOMEhome是两个不同的变量。

查看单个环境变量的值,可以使用printenv命令或echo命令。


  
  1. $ printenv PATH
  2. # 或者
  3. $ echo $PATH

注意,printenv命令后面的变量名,不用加前缀$

自定义变量是用户在当前 Shell 里面自己定义的变量,必须先定义后使用,而且仅在当前 Shell 可用。一旦退出当前 Shell,该变量就不存在了。

set命令可以显示所有变量(包括环境变量和自定义变量),以及所有的 Bash 函数。

$ set
 

 

创建变量

用户创建变量的时候,变量名必须遵守下面的规则。

  • 字母、数字和下划线字符组成。
  • 第一个字符必须是一个字母或一个下划线,不能是数字。
  • 不允许出现空格和标点符号。

变量声明的语法如下。

variable=value
 

上面命令中,等号左边是变量名,右边是变量。注意,等号两边不能有空格。

如果变量的值包含空格,则必须将值放在引号中。

myvar="hello world"
 

Bash 没有数据类型的概念,所有的变量值都是字符串。

下面是一些自定义变量的例子。


  
  1. a=z # 变量 a 赋值为字符串 z
  2. b="a string" # 变量值包含空格,就必须放在引号里面
  3. c="a string and $b" # 变量值可以引用其他变量的值
  4. d="\t\ta string\n" # 变量值可以使用转义字符
  5. e=$(ls -l foo.txt) # 变量值可以是命令的执行结果
  6. f=$((5 * 7)) # 变量值可以是数学运算的结果

变量可以重复赋值,后面的赋值会覆盖前面的赋值。


  
  1. $ foo=1
  2. $ foo=2
  3. $ echo $foo
  4. 2

上面例子中,变量foo的第二次赋值会覆盖第一次赋值。

 

读取变量

读取变量的时候,直接在变量名前加上$就可以了。


  
  1. $ foo=bar
  2. $ echo $foo
  3. bar

每当 Shell 看到以$开头的单词时,就会尝试读取这个变量名对应的值。

如果变量不存在,Bash 不会报错,而会输出空字符。

由于$在 Bash 中有特殊含义,把它当作美元符号使用时,一定要非常小心,


  
  1. $ echo The total is $100.00
  2. The total is 00.00

上面命令的原意是输入$100,但是 Bash 将$1解释成了变量,该变量为空,因此输入就变成了00.00。所以,如果要使用$的原义,需要在$前面放上反斜杠,进行转义。


  
  1. $ echo The total is \$100.00
  2. The total is $100.00

读取变量的时候,变量名也可以使用花括号{}包围,比如$a也可以写成${a}。这种写法可以用于变量名与其他字符连用的情况。


  
  1. $ a=foo
  2. $ echo $a_file
  3. $ echo ${a}_file
  4. foo_file

上面代码中,变量名a_file不会有任何输出,因为 Bash 将其整个解释为变量,而这个变量是不存在的。只有用花括号区分$a,Bash 才能正确解读。

事实上,读取变量的语法$foo,可以看作是${foo}的简写形式。

如果变量的值本身也是变量,可以使用${!varname}的语法,读取最终的值。


  
  1. $ myvar=USER
  2. $ echo ${!myvar}
  3. ruanyf

上面的例子中,变量myvar的值是USER${!myvar}的写法将其展开成最终的值。

 

删除变量

unset命令用来删除一个变量。

unset NAME
 

这个命令不是很有用。因为不存在的 Bash 变量一律等于空字符串,所以即使unset命令删除了变量,还是可以读取这个变量,值为空字符串。

所以,删除一个变量,也可以将这个变量设成空字符串。


  
  1. $ foo=''
  2. $ foo=

上面两种写法,都是删除了变量foo。由于不存在的值默认为空字符串,所以后一种写法可以在等号右边不写任何值。

 

输出变量,export 命令

用户创建的变量仅可用于当前 Shell,子 Shell 默认读取不到父 Shell 定义的变量。为了把变量传递给子 Shell,需要使用export命令。这样输出的变量,对于子 Shell 来说就是环境变量。

export命令用来向子 Shell 输出变量。


  
  1. NAME=foo
  2. export NAME

上面命令输出了变量NAME。变量的赋值和输出也可以在一个步骤中完成。

export NAME=value
 

上面命令执行后,当前 Shell 及随后新建的子 Shell,都可以读取变量$NAME

子 Shell 如果修改继承的变量,不会影响父 Shell。


  
  1. # 输出变量 $foo
  2. $ export foo=bar
  3. # 新建子 Shell
  4. $ bash
  5. # 读取 $foo
  6. $ echo $foo
  7. bar
  8. # 修改继承的变量
  9. $ foo=baz
  10. # 退出子 Shell
  11. $ exit
  12. # 读取 $foo
  13. $ echo $foo
  14. bar

上面例子中,子 Shell 修改了继承的变量$foo,对父 Shell 没有影响。

 

特殊变量

Bash 提供一些特殊变量。这些变量的值由 Shell 提供,用户不能进行赋值。

(1)$?

$?为上一个命令的退出码,用来判断上一个命令是否执行成功。返回值是0,表示上一个命令执行成功;如果是非零,上一个命令执行失败。


  
  1. $ ls doesnotexist
  2. ls: doesnotexist: No such file or directory
  3. $ echo $?
  4. 1

上面例子中,ls命令查看一个不存在的文件,导致报错。$?为1,表示上一个命令执行失败。

(2)$$

$$为当前 Shell 的进程 ID。


  
  1. $ echo $$
  2. 10662

这个特殊变量可以用来命名临时文件。

LOGFILE=/tmp/output_log.$$
 

(3)$_

$_为上一个命令的最后一个参数。


  
  1. $ grep dictionary /usr/share/dict/words
  2. dictionary
  3. $ echo $_
  4. /usr/share/dict/words

(4)$!

$!为最近一个后台执行的异步命令的进程 ID。


  
  1. $ firefox &
  2. [1] 11064
  3. $ echo $!
  4. 11064

上面例子中,firefox是后台运行的命令,$!返回该命令的进程 ID。

(5)$0

$0为当前 Shell 的名称(在命令行直接执行时)或者脚本名(在脚本中执行时)。


  
  1. $ echo $0
  2. bash

上面例子中,$0返回当前运行的是 Bash。

(6)$-

$-为当前 Shell 的启动参数。


  
  1. $ echo $-
  2. himBHs

(7)$@$#

$@$#表示脚本的参数数量,参见脚本一章。

 

变量的默认值

Bash 提供四个特殊语法,跟变量的默认值有关,目的是保证变量不为空。

${varname:-word}
 

上面语法的含义是,如果变量varname存在且不为空,则返回它的值,否则返回word。它的目的是返回一个默认值,比如${count:-0}表示变量count不存在时返回0

${varname:=word}
 

上面语法的含义是,如果变量varname存在且不为空,则返回它的值,否则将它设为word,并且返回word。它的目的是设置变量的默认值,比如${count:=0}表示变量count不存在时返回0,且将count设为0

${varname:+word}
 

上面语法的含义是,如果变量名存在且不为空,则返回word,否则返回空值。它的目的是测试变量是否存在,比如${count:+1}表示变量count存在时返回1(表示true),否则返回空值。

${varname:?message}
 

上面语法的含义是,如果变量varname存在且不为空,则返回它的值,否则打印出varname: message,并中断脚本的执行。如果省略了message,则输出默认的信息“parameter null or not set.”。它的目的是防止变量未定义,比如${count:?"undefined!"}表示变量count未定义时就中断执行,抛出错误,返回给定的报错信息undefined!

上面四种语法如果用在脚本中,变量名的部分可以用到数字19,表示脚本的参数。

filename=${1:?"filename missing."}
 

上面代码出现在脚本中,1表示脚本的第一个参数。如果该参数不存在,就退出脚本并报错。

 

declare 命令

declare命令可以声明一些特殊类型的变量,为变量设置一些限制,比如声明只读类型的变量和整数类型的变量。

它的语法形式如下。

declare OPTION VARIABLE=value
 

declare命令的主要参数(OPTION)如下。

  • -a:声明数组变量。
  • -f:输出所有函数定义。
  • -F:输出所有函数名。
  • -i:声明整数变量。
  • -l:声明变量为小写字母。
  • -p:查看变量信息。
  • -r:声明只读变量。
  • -u:声明变量为大写字母。
  • -x:该变量输出为环境变量。

declare命令如果用在函数中,声明的变量只在函数内部有效,等同于local命令。

不带任何参数时,declare命令输出当前环境的所有变量,包括函数在内,等同于不带有任何参数的set命令。

$ declare
 

(1)-i参数

-i参数声明整数变量以后,可以直接进行数学运算。


  
  1. $ declare -i val1=12 val2=5
  2. $ declare -i result
  3. $ result=val1*val2
  4. $ echo $result
  5. 60

上面例子中,如果变量result不声明为整数,val1*val2会被当作字面量,不会进行整数运算。另外,val1val2其实不需要声明为整数,因为只要result声明为整数,它的赋值就会自动解释为整数运算。

注意,一个变量声明为整数以后,依然可以被改写为字符串。


  
  1. $ declare -i var=12
  2. $ var=foo
  3. $ echo $var
  4. 0

上面例子中,变量var声明为整数,覆盖以后,Bash 不会报错,但会赋以不确定的值,上面的例子中可能输出0,也可能输出的是3。

(2)-x参数

-x参数等同于export命令,可以输出一个变量为子 Shell 的环境变量。


  
  1. $ declare -x foo
  2. # 等同于
  3. $ export foo

(3)-r参数

-r参数可以声明只读变量,无法改变变量值,也不能unset变量。


  
  1. $ declare -r bar=1
  2. $ bar=2
  3. bash: bar:只读变量
  4. $ echo $?
  5. 1
  6. $ unset bar
  7. bash: bar:只读变量
  8. $ echo $?
  9. 1

上面例子中,后两个赋值语句都会报错,命令执行失败。

(4)-u参数

-u参数声明变量为大写字母,可以自动把变量值转成大写字母。


  
  1. $ declare -u foo
  2. $ foo=upper
  3. $ echo $foo
  4. UPPER

(5)-l参数

-l参数声明变量为小写字母,可以自动把变量值转成小写字母。


  
  1. $ declare -l bar
  2. $ bar=LOWER
  3. $ echo $bar
  4. lower

(6)-p参数

-p参数输出变量信息。


  
  1. $ foo=hello
  2. $ declare -p foo
  3. declare -- foo="hello"
  4. $ declare -p bar
  5. bar:未找到

上面例子中,declare -p可以输出已定义变量的值,对于未定义的变量,会提示找不到。

如果不提供变量名,declare -p输出所有变量的信息。

$ declare -p
 
$ declare -p

 

(7)-f参数

-f参数输出当前环境的所有函数,包括它的定义。

$ declare -f
 

(8)-F参数

-F参数输出当前环境的所有函数名,不包含函数定义。

$ declare -F
 

 

readonly 命令

readonly命令等同于declare -r,用来声明只读变量,不能改变变量值,也不能unset变量。


  
  1. $ readonly foo=1
  2. $ foo=2
  3. bash: foo:只读变量
  4. $ echo $?
  5. 1

上面例子中,更改只读变量foo会报错,命令执行失败。

readonly命令有三个参数。

  • -f:声明的变量为函数名。
  • -p:打印出所有的只读变量。
  • -a:声明的变量为数组。

 

let 命令

let命令声明变量时,可以直接执行算术表达式。


  
  1. $ let foo=1+2
  2. $ echo $foo
  3. 3

上面例子中,let命令可以直接计算1 + 2

let命令的参数表达式如果包含空格,就需要使用引号。

$ let "foo = 1 + 2"
 

let可以同时对多个变量赋值,赋值表达式之间使用空格分隔。


  
  1. $ let "v1 = 1" "v2 = v1++"
  2. $ echo $v1,$v2
  3. 2,1

上面例子中,let声明了两个变量v1v2,其中v2等于v1++,表示先返回v1的值,然后v1自增。

 

 

下一节Bash脚本教程之字符串操作

文章来源: sunmenglei.blog.csdn.net,作者:孙叫兽,版权归原作者所有,如需转载,请联系作者。

原文链接:sunmenglei.blog.csdn.net/article/details/107169689

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。