Linux基础(23)之bash中的变量

Linux基础(23)之bash中的变量

微信搜索 zze_coding 或扫描 👉 二维码关注我的微信公众号获取更多资源推送:

bash中的变量

bash 是一门弱类型脚本语言你,变量默认均为字符型,参与运算时会自动进行隐式类型转换,变量无需事先定义可直接使用。

bash中变量的种类

这里种类的划分是根据变量的生效范围等标准。

本地变量

生效范围为当前 shell 进程的生命周期,对当前 shell 之外的其它 shell 进程,包括当前 shell 的 子 shell 进程均无效。
例:

[root@localhost ~]# a=1
[root@localhost ~]# echo $a
1
[root@localhost ~]# bash
[root@localhost ~]# echo $a

[root@localhost ~]# exit
exit
[root@localhost ~]# echo $a
1

环境变量

生效范围为当前 shell 进程及其子进程。
环境变量的定义有如下两种方式:
1、使用 declare 命令,且要使用其-x 选项,例:

[root@localhost ~]# declare -x b=2
[root@localhost ~]# echo $b
2
[root@localhost ~]# bash
[root@localhost ~]# echo $b
2

2、使用 export 命令,例:

[root@localhost ~]# export c=3
[root@localhost ~]# echo $c
3
[root@localhost ~]# bash
[root@localhost ~]# echo $c
3

declare -xexport 实际上都是将一个变量导出为环境变量,如果有一个已存在的本地变量,要将其导出为环境变量,也可使用这两个命令,例:

[root@localhost ~]# d=4
[root@localhost ~]# export d
[root@localhost ~]# echo $d
4
[root@localhost ~]# bash
[root@localhost ~]# echo $d
4
[root@localhost ~]# exit
exit
[root@localhost ~]# e=5
[root@localhost ~]# declare -x e
[root@localhost ~]# echo $e
5
[root@localhost ~]# bash 
[root@localhost ~]# echo $e
5

局部变量

生效范围为当前 shell 进程中某一个代码片段,通常指函数。

位置变量

位置变量使用 $1$2 、... 来表示,用于让脚本在脚本代码中调用通过命令行传递给它的参数,$1$2 在分别表示调用脚本时传递的第 1 和 第 2 个参数。
例:
编写名为 posvar.sh 的 shell 脚本,内容如下:

#!/bin/bash
echo $1
echo $2

给予其运行权限并在执行时传入参数:

[root@localhost ~]# chmod +x posvar.sh
[root@localhost ~]# ./posvar.sh tom jerry
tom
jerry

位置变量中有一个换挡操作,所谓换挡就是从第一个参数开始依次踢出参数,通过 shift 命令来实现。
例:修改 posvar.sh 脚本内容如下:

#!/bin/bash
echo $1
shift
echo $1
shift 2
echo $1

执行,传入参数如下:

[root@localhost ~]# ./test.sh 1 2 3 4
1
2
4

描述:在执行第一个 echo $1 时输出了第一个参数即 1,接着使用 shift 踢出了第 1 个参数,所以接着第二个 echo $1 输出的就是第二个参数即 2,输出以后又通过 shift 2 踢出了第二个和第三个参数即 23,所以最后一个 echo $1 输出的是 4

特殊变量

特殊变量是 bash 内置的用来保存特殊数据的变量。

  • $? : 表示在 bash 中执行的最后一条命令返回的状态;
  • $0 :执行脚本时的命令本身;
  • $* :传递给脚本的所有参数,把所有参数当做一个字符串,用空白字符隔开;
  • $@ :传递给脚本的所有参数,把传递的每一个参数当做一个独立的字符串;
  • $# :传递给脚本的参数个数;

例:
编辑名为 test.sh 的 shell 脚本内容如下:

#!/bin/bash
echo $0
echo "\$*:$*"
echo "\$@:$@"
echo "\$#:$#"

给予其执行权限,执行时传入参数,如下:

[root@localhost ~]# chmod +x test.sh 
[root@localhost ~]# ./test.sh tom jerry tiger
./test.sh
$*:tom jerry tiger
$@:tom jerry tiger
$#:3

只读变量

如果想定义一个只读变量,可使用 readonlydeclare -r 命令,例:

[root@localhost ~]# readonly name=1
[root@localhost ~]# name=2
bash: name: 只读变量

只读变量不能被手动销毁,只能等到 shell 进程终止时只读变量随之销毁,例:

[root@localhost ~]# unset name
bash: unset: name: 无法反设定: 只读 variable

如果要将一个已定义的变量更改为只读变量仍然可以使用 readonly VARNAMEdeclare -r VARNAME 命令,例:

[root@localhost ~]# declare -r a
[root@localhost ~]# a=2
-bash: a: 只读变量

变量的赋值与引用

赋值

bash 中变量赋值的格式如下:

name=value

value 的取值:

  • 可以直接是字符串,如 name="username"
  • 可以是变量的引用,如 name="$username"
  • 命令引用,指的是将一个命令的执行结果赋值给指定变量,如 name=`COMMAND`name=$(COMMAND)

例:将 root 用户的 UID 值赋值给 rootUID 变量并输出。

[root@localhost ~]# rootUID=$(id -u root)
[root@localhost ~]# echo $rootUID 
0

引用

如果要引用上述的 name 变量,那么可以使用 $name${name} 的方式来引用,大多数情况下 {} 是可省略的。
例:

[root@localhost ~]# name=value
[root@localhost ~]# echo $name
value
[root@localhost ~]# echo ${name}
value

变量的引用又分为强引用和弱引用,通过 '" 来区分:

  • ' :弱引用,其中的变量引用会被替换为变量值;
  • " :强引用,其中的变量引用不会被替换为变量值,而保持变量名字符串;

查看与销毁变量

查看已定义的所有变量

查看以定义的变量可以使用 set 命令,例:

[root@localhost ~]# set 
BASH=/bin/bash
BASHOPTS=checkwinsize:cmdhist:expand_aliases:extquote:force_fignore:histappend:hostcomplete:interactive_comments:login_shell:progcomp:promptvars:sourcepath
BASH_ALIASES=()
BASH_ARGC=()
BASH_ARGV=()
...

查看所有环境变量

可使用 exportenvprintenv 命令来查看当前已有的环境变量,例:

[root@localhost ~]# export
declare -x HISTCONTROL="ignoredups"
declare -x HISTSIZE="1000"
declare -x HOME="/root"
declare -x HOSTNAME="localhost.localdomain"
declare -x LANG="zh_CN.UTF-8"
...
[root@localhost ~]# env
XDG_SESSION_ID=20
HOSTNAME=localhost.localdomain
SELINUX_ROLE_REQUESTED=
SHELL=/bin/bash
...
[root@localhost ~]# printenv
XDG_SESSION_ID=20
HOSTNAME=localhost.localdomain
SELINUX_ROLE_REQUESTED=
SHELL=/bin/bash
...

bash 中有许多内建的环境变量,例如:PATHSHELLUIDHISTSIZEHOMEPWDOLDHISTSIZEPS1 等等。

销毁变量

bash 中使用 unset VARNAME 来销毁变量,例:

[root@localhost ~]# name=zze
[root@localhost ~]# echo $name
zze
[root@localhost ~]# unset name
[root@localhost ~]# echo $name

变量的命名法则

  1. 不能使用程序中的保留字,例如 iffor 等等;
  2. 只能使用数字、字幕及下划线,且不能以数字开头;
  3. 见名知义;

补充

pstree

pstree 命令可以查看当前系统的进程树,例:

[root@localhost ~]# pstree
systemd─┬─NetworkManager─┬─dhclient
        │                └─2*[{NetworkManager}]
        ├─VGAuthService
        ├─auditd───{auditd}
        ├─chronyd
        ├─crond
        ├─dbus-daemon───{dbus-daemon}
        ├─dockerd-current─┬─docker-containe───7*[{docker-containe}]
        │                 └─9*[{dockerd-current}]
        ├─firewalld───{firewalld}
        ├─login───bash
        ├─lvmetad
        ├─master─┬─pickup
        │        └─qmgr
        ├─polkitd───6*[{polkitd}]
        ├─rsyslogd───2*[{rsyslogd}]
        ├─sshd───sshd───bash───pstree
        ├─systemd-journal
        ├─systemd-logind
        ├─systemd-udevd
        ├─tuned───4*[{tuned}]
        └─vmtoolsd───{vmtoolsd}

sshd 节点下可以查看到当前系统的 shell 进程信息,如通过 bash 开启一个子 shell 进程,再通过 pstree 命令查看:

[root@localhost ~]# bash 
[root@localhost ~]# pstree
systemd─┬─NetworkManager─┬─dhclient
        │                └─2*[{NetworkManager}]
        ├─VGAuthService
        ├─auditd───{auditd}
        ├─chronyd
        ├─crond
        ├─dbus-daemon───{dbus-daemon}
        ├─dockerd-current─┬─docker-containe───7*[{docker-containe}]
        │                 └─9*[{dockerd-current}]
        ├─firewalld───{firewalld}
        ├─login───bash
        ├─lvmetad
        ├─master─┬─pickup
        │        └─qmgr
        ├─polkitd───6*[{polkitd}]
        ├─rsyslogd───2*[{rsyslogd}]
        ├─sshd───sshd───bash───bash───pstree
        ├─systemd-journal
        ├─systemd-logind
        ├─systemd-udevd
        ├─tuned───4*[{tuned}]
        └─vmtoolsd───{vmtoolsd}

可以看到 sshd 节点下的 bash 进程下又有一个 bash 进程。

练习

写一个能输出给定文件的函数的脚本。
1、新建一个名为 linecount.sh 的脚本文件,内容如下:

#!/bin/bash
linecount="$(wc -l $1 | cut -d' ' -f1)"
echo "$1 has $linecount lines."

2、测试使用:

[root@localhost ~]# ./linecount.sh /etc/passwd
/etc/passwd has 26 lines.

Copyright: 采用 知识共享署名4.0 国际许可协议进行许可

Links: https://www.zze.xyz/archives/linux-base-23.html

Buy me a cup of coffee ☕.