Bash 变量

1月13日,打卡额外学习,嘻嘻

内容来自实验楼

shell 变量
  • 没有众多的存储类及类型限制,都是字符串
  • 不需要预先定义,可以直接赋值
变量的定义

变量定义的格式如下:

变量名=字符串
变量名

shell 中的变量名可以由字母,数字,下划线组成。

  • 但是只能由字母或下划线开头。
  • 建议不使用命令关键字,如定义的变量名不可以为 echorm 等命令。(可用 help 命令查看保留关键字)

如下示例:

# 正确的定义
user2=shiyanlou002
_user3=shiyanlou003

# 错误的定义
4user=shiyanlou004
变量赋值

直接赋值:

shell 中,变量是无类型的,即所有变量的值都是一串字符,即字符串,当然,也可以为空字符串。

对于变量的赋值需要注意的是:

  • 在等号 = 的两边不能有空格
  • 如果在变量的值中包含空格,需要使用单引号 '' 或者双引号 ""
  • 如果赋值的是一个已存在的变量名,则会覆盖掉原有的内容

命令结果进行赋值:

除了使用上述的方式对变量进行赋值之外,我们还可以使用命令执行的结果进行赋值。一般有两种方式:

  • 反引号 ( ` )

    使用反引号我们可以在字符串中执行命令,也可以直接引用命令执行的结果进行赋值,如下示例:

    # 直接使用反引号进行赋值
    user1=`echo shiyanlou`
    
    # 也可以在字符串中执行命令
    user2="shiyanlou `echo MM`"
    

    而对于在字符串中使用反引号执行命令,如果需要使用引号的话,则只能使用双引号。

  • $(command)

    直接将命令写在括号中即可,如下:

    # 使用 $() 进行赋值
    user1=$(echo syl001)
    
    # 查看 user1
    echo $user1
    

对于使用反引号或者使用 $(command) 的方式又被称为命令替换,即使用命令的输出来替换命令本身

使用read定义

除了使用上述的方式定义变量之外,我们还可以使用 read

read 命令可以读取标准输入的内容,然后将其赋值给一个变量或数组,多用于接收用户输入。这里我们仅仅介绍使用 read 定义变量,关于数组的内容在后面我们会学习到。

常用的用法如下:

read: 用法: read [-s 关闭回显] [-a 数组] [-n 读取字符数] [-p 提示符] [-t 超时] [名称 ...]

如下,我们通过示例来学习相关的参数的使用:

# 读取用户输入赋值给变量 user1,输入完成后使用回车即可
$ read user1

# 读取用户输入赋值给多个变量,user2,user3,输入的时候需要使用空格分隔
$ read user2 user3

# 使用命令提示符,提示输入
$ read -p "please enter your username:" user4

# -t 指定超时时间,即等待用户输入的时间,不会一直等待用户的输入,设置的时间单位为秒
$ read -p "username:" -t 5 user6 user7

# -s 不会显示输入的内容,
$ read -s user8
使用 declare 定义

declare 属于 bash 的内建命令,可以声明变量并赋值给声明的变量属性值。

常用的选项如下:

  • -r 设置只读,
  • -l 使值中所有的大写字母转换为小写
  • -u 小写转换为大写
$ declare user1=shiyanlou001
$ echo $user1
shiyanlou001

$ declare -r user2=shiyanlou2
$ echo $user2
shiyanlou2
$ user2=test
-bash: user2: readonly variable
引用变量$

之前使用 echo 输出变量时需要在变量名前面加 $ 符号,这是因为在 shell 中变量是无类型的。

而为了区分到底引用的是变量的值还是字符串,需要在变量名前面使用美元符号 $

引号的使用

在使用变量时,如果变量存在于引号内,则必须使用双引号

如下示例:

# 首先定义 user1 变量
user1=syl001

# 正确的引用,在 user2 中使用,不使用引号
user2=hello$user1

# 正确的引用,在 user2 中使用,使用双引号
user2="hello $user1"

# 正确的引用,
user2="hello"$user1"hello"
user2='hello'$user1'hello'

# 错误的引用,在 user2 中引用,使用单引号
user2='hello $user1'
扩展变量${}

引用变量除了使用 $var 格式直接引用变量之外,还可以使用 ${var} 的方式对变量进行扩展。常见的形式如下表:

表达式说明
${var}等同于 $var
${var:-word}如果 $var 的变量值为空或未赋值,则返回 word 字符串,防止变量为空值或因未定义而导致异常 。
${var:=word}如果 $var 的变量值为空或未赋值,则设置这个变量值为 word,并返回其值。位置变量和特殊变量不适用。基本同上一个,但该变量又额外给 $var 变量赋值了。
${var:?word}如果 $var 变量值为空或未赋值,那么 word 字符串将被作为标准错误输出,否则输出变量的值。用于捕捉由于变量未定义而导致的错误,并退出程序。
${var:+word}如果 $var 变量值为空或未赋值,则什么都不做,否则返回 word 字符串的值,也就是整个表达式的值为 word 。

同上述内容一样,使用 ${var}及其扩展方式不适用于单引号。

如下示例,编写 test1.sh 脚本:

#!/bin/bash

# 定义 $user1 变量
user1=syl001

# 打印 $user1 变量
echo $user1 ${user1}
syl001 syl001

# 打印 $user1  $user2。而 $user2 不存在,打印 syl002
echo $user1 ${user2:-syl002}
syl001 syl002

# 上一步并未设置 $user2 的值,所以这里只能打印出 $user1
echo $user1 $user2
syl001 

# 打印 $user1 并设置 $user2 的值
echo $user1 ${user2:=syl002}
syl001 syl002

# 此时,能够打印出 $user1 $user2
echo $user1 $user2
syl001 syl002
特殊变量
位置参数

位置参数代表的是 bash 脚本执行时的命令行参数,也代表 bash 脚本中定义的函数参数,而关于函数的内容在后面的章节中我们会学习到。

如下表中的位置参数:

变量含义
$n传递给脚本或函数的参数。n 是一个非负的整数,表示第几个参数。例如,第一个参数是 $1,第二个参数是 $2。在 n 大于等于 10 的时候,需要使用 ${n}

如下示例,我们编辑 test2.sh 脚本文件:

#!/bin/bash

echo $1 $2 $3

echo ${12} $12

使用如下语句运行:

$ bash test2.sh 1 2 3 4 5 6 7 8 9 0 a b c
1 2 3
b 12
其它特殊参数

除此之外,还有一些特殊的参数,这些变量仅仅可以被引用,而不可以被修改,说明如下:

变量含义
$0当前脚本的文件名
$#传递给脚本或函数的参数数量
$*传递给脚本或函数的所有参数
$?获取执行上一个指令的执行状态返回值(0 为成功,非零为失败),我们之前已经用到了
$$获取当前执行的 shell 脚本的进程号(PID)
$!获取上一个在后台工作的进程的进程号
$_获取在此之前执行的命令或脚本的最后一个参数

我们通过示例来学习这一部分内容,编写 test.sh 脚本文件:

#!/bin/bash

# 打印所有的参数个数
echo $#

# 打印所有的位置参数
echo ${*:-"no parameter"}

# 打印当前执行的进程号
echo $$

# 打印之前命令的最后一个参数,也就是进程号
echo $_
ubuntu@VM-0-5-ubuntu:~$ bash test.sh
0
no parameter
8927
8927
ubuntu@VM-0-5-ubuntu:~$ bash test.sh 1 2 3 a b c
6
1 2 3 a b c
9068
9068
ubuntu@VM-0-5-ubuntu:~$ echo $_
c
删除变量

对于定义的变量我们可以使用 unset 命令进行删除操作,两个常用的选项如下:

  • -f 仅删除函数
  • -v 仅删除变量

如下示例,我们定义变量,然后将其删除:

# 定义
user1=shiyanlou001
user2=shiyanlou002

# 查看值
echo $user1 $user2

# 删除
unset user1 user2

# 删除后再次查看
echo $user1 $user2