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 -x
和 export
实际上都是将一个变量导出为环境变量,如果有一个已存在的本地变量,要将其导出为环境变量,也可使用这两个命令,例:
[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
踢出了第二个和第三个参数即 2
、3
,所以最后一个 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
只读变量
如果想定义一个只读变量,可使用 readonly
或 declare -r
命令,例:
[root@localhost ~]# readonly name=1
[root@localhost ~]# name=2
bash: name: 只读变量
只读变量不能被手动销毁,只能等到 shell 进程终止时只读变量随之销毁,例:
[root@localhost ~]# unset name
bash: unset: name: 无法反设定: 只读 variable
如果要将一个已定义的变量更改为只读变量仍然可以使用 readonly VARNAME
或 declare -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=()
...
查看所有环境变量
可使用 export
、env
或 printenv
命令来查看当前已有的环境变量,例:
[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 中有许多内建的环境变量,例如:
PATH
、SHELL
、UID
、HISTSIZE
、HOME
、PWD
、OLD
、HISTSIZE
、PS1
等等。
销毁变量
bash 中使用 unset VARNAME
来销毁变量,例:
[root@localhost ~]# name=zze
[root@localhost ~]# echo $name
zze
[root@localhost ~]# unset name
[root@localhost ~]# echo $name
变量的命名法则
- 不能使用程序中的保留字,例如
if
、for
等等; - 只能使用数字、字幕及下划线,且不能以数字开头;
- 见名知义;
补充
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.
评论区