1、变量和参数的介绍
(1)变量替换
$(…)
使用 $(…) 机制来进行变量赋值(这是一种比后置引用(反引号`)更新的一种方法)。 事实上这两种方法都是命令替换的一种形式。
arch=$(uname -m)
(2)特殊的变量类型
export
一个脚本只能够 export 变量到这个脚本所产生的子进程, 也就是说只能够对这个脚本所产生的命令和进程起作用。 如果脚本是从命令行中调用的, 那么这个脚本所 export 的变量是不能影响命令行环境的。 也就是说, 子进程是不能够 export 变量来影响产生自己的父进程的环境的。
位置参数
从命令行传递到脚本的参数: 0,0, 1, 2,2, 3 . . .
0就是脚本文件自身的名字,0 就是脚本文件自身的名字, 1 是第一个参数, 2是第二个参数,2 是第二个参数, 3 是第三个参数, 然后是第四个。 9之后的位置参数就必须用大括号括起来了,比如,9 之后的位置参数就必须用大括号括起来了, 比如, {10}, 11,{11}, {12} 。
两个比较特殊的变量 $* 和 $@ 表示所有的位置参数。
shift
shift 命令会重新分配位置参数, 其实就是把所有的位置参数都向左移动一个位置。
1<—1 <— 2, 2<—2 <— 3, 3<—3 <— 4, 等等。
原来的 1就消失了,但是1 就消失了, 但是 0 (脚本名) 是不会改变的。 如果传递了大量的位置参数到脚本中, 那么 shift 命令允许你访问的位置参数的数量超过 10 个, 当然 {} 标记法也提供了这样的功能。
2、引用
(1)引用变量
双引号中通过直接使用变量名的方法来引用变量。单引号 (’ ') 操作与双引号基本一样, 但是不允许引用变量, 因为 $ 的特殊意义被关闭了。
(2)转义
- \0xx
转换为八进制的 ASCII 码, 等价于 0xx
3、条件判断
(1)条件测试结构
- test, /usr/bin/test, [ ], 和 /usr/bin/[ 都是等价命令
- [[ ]] 结构比 [ ] 结构更加通用。 这是一个扩展的 test 命令, 是从 ksh88 中引进的。
- (( )) 结构扩展并计算一个算术表达式的值
(2)文件测试操作符
- -e
文件存在 - -a
文件存在。这个选项的效果与 -e 相同。 但是它已经被 “弃用” 了, 并且不鼓励使用。 - -f
表示这个文件是一个一般文件 (并不是目录或者设备文件) - -s
- 文件大小不为零
- -d
表示这是一个目录 - -b
表示这是一个块设备 (软盘, 光驱, 等等。) - -c
表示这是一个字符设备 (键盘, modem, 声卡, 等等。) - -p
这个文件是一个管道 - -h
这是一个符号链接 - -L
这是一个符号链接 - -S
表示这是一个 socket - -t
- 文件(描述符)被关联到一个终端设备上。这个测试选项一般被用来检测脚本中的 stdin([ -t 0 ]) 或者 stdout([ -t 1 ]) 是否来自于一个终端。
- -r
- 文件是否具有可读权限(指的是正在运行这个测试命令的用户是否具有读权限)
- -w
文件是否具有可写权限(指的是正在运行这个测试命令的用户是否具有写权限) - -x
- 文件是否具有可执行权限(指的是正在运行这个测试命令的用户是否具有可执行权限)
- -g
set-group-id(sgid) 标记被设置到文件或目录上。 - 如果目录具有 sgid 标记的话, 那么在这个目录下所创建的文件将属于拥有这个目录的用户组, 而不必是创建这个文件的用户组。 这个特性对于在一个工作组中共享目录非常有用。
- -u
set-user-id (suid) 标记被设置到文件上。 - 如果一个 root 用户所拥有的二进制可执行文件设置了 set-user-id 标记位的话, 那么普通用户也会以 root 权限来运行这个文件。
- -k
- 设置粘贴位
对于 “粘贴位” 的一般了解, save-text-mode 标志是一个文件权限的特殊类型。 如果文件设置了这个标志, 那么这个文件将会被保存到缓存中, 这样可以提高访问速度。 - -O
判断你是否是文件的拥有者 - -G
- 文件的 group-id 是否与你的相同
- -N
从文件上一次被读取到现在为止, 文件是否被修改过 - f1 -nt f2
文件 f1 比文件 f2 新 - f1 -ot f2
文件 f1 比文件 f2 旧
- f1 -ef f2
文件 f1 和文件 f2 是相同文件的硬链接 - !
“非” —— 反转上边所有测试的结果(如果没给出条件, 那么返回真)。
(3)其他比较操作符
二元比较操作符用来比较两个变量或数字。 注意整数比较与字符串比较的区别。
整数比较
- -eq
等于
if [ “a”−eq“a” -eq “b” ] - -ne
不等于
if [ “a”−ne“a” -ne “b” ] - -gt
大于
if [ “a”−gt“a” -gt “b” ] - -ge
大于等于
if [ “a”−ge“a” -ge “b” ] - -lt
小于
if [ “a”−lt“a” -lt “b” ] - -le
小于等于
if [ “a”−le“a” -le “b” ]
<
小于(在双括号中使用)
((“a”<“a” < “b”))
<=
小于等于(在双括号中使用)
((“a " < = " a" <= "a"<="b”))
>
大于(在双括号中使用)
((“a”>“a” > “b”))
- >=
大于等于(在双括号中使用)
((“a”>=“a” >= “b”))
字符串比较
- =
等于
if [ “a”=“a” = “b” ] - ==
等于
if [ “a”==“a” == “b” ]
与 = 等价。 - !=
不等号
if [ “a”!=“a” != “b” ]
这个操作符将在 [[ … ]] 结构中使用模式匹配。 - <
小于, 按照 ASCII 字符进行排序
if [[ “a”<“a” < “b” ]]
if [ “$a” \< “$b” ]
注意 “<” 使用在 [ ] 结构中的时候需要被转义。 - >
大于, 按照 ASCII 字符进行排序
if [[ “a”>“a” > “b” ]]
if [ “a”“a” \> “b” ]
注意 “>” 使用在 [ ] 结构中的时候需要被转义。
- -z
字符串为 “null” , 意思就是字符串长度为零 - -n
字符串不为 “null” 。
compound comparison
- -a
逻辑与
exp1 -a exp2 如果表达式 exp1 和 exp2 都为真的话, 那么结果为真。 - -o
逻辑或
exp1 -o exp2 如果表达式 exp1 和 exp2 中至少有一个为真的话, 那么结果为真。
4、数字常量
shell 脚本在默认情况下都是把数字作为 10 进制数来处理, 除非这个数字采用了特殊的标记或者前缀。
如果数字以 0 开头的话那么就是 8 进制数。 如果数字以 0x 开头的话那么就是 16 进制数。 如果数字中间嵌入了 # 的话, 那么就被认为是 BASE#NUMBER 形式的标记法(有范围和符号限制)。
# 其他进制: BASE#NUMBER # BASE 的范围在 2 到 64 之间. # NUMBER 的值必须使用 BASE 范围内的符号来表示, 具体看下边的示例. let "bin = 2#111100111001101" echo "binary number = $bin" # 31181 let "b32 = 32#77" echo "base-32 number = $b32" # 231
5、变量重游
(1) 内部变量
内建变量
这些变量将会影响 bash 脚本的行为。
- $BASH
Bash 的二进制程序文件的路径
$ echo $BASH /bin/bash
- $BASH_ENV
这个环境变量会指向一个 Bash 的启动文件, 当一个脚本被调用的时候, 这个启动文件将会被读取。 - $BASH_SUBSHELL
- 这个变量用来提示子 shell 的层次。 这是一个 Bash 的新特性, 直到版本 3 的 Bash 才被引入近来。
- $BASH_VERSINFO[n]
- 这是一个含有 6 个元素的数组, 它包含了所安装的 Bash 的版本信息。 这与下边的 $BASH_VERSION 很相像, 但是这个更加详细一些。
# Bash version info: for n in 0 1 2 3 4 5; do echo "BASH_VERSINFO[$n] = ${BASH_VERSINFO[$n]}" done # BASH_VERSINFO[0] = 3 # 主版本号 # BASH_VERSINFO[1] = 00 # 次版本号。 # BASH_VERSINFO[2] = 14 # 补丁次数。 # BASH_VERSINFO[3] = 1 # 编译版本。 # BASH_VERSINFO[4] = release # 发行状态。 # BASH_VERSINFO[5] = i386-redhat-linux-gnu # 结构体系 # (与变量$MACHTYPE相同)。
- $BASH_VERSION
安装在系统上的 Bash 版本号
bash$ echo $BASH_VERSION 3.00.14(1)-release tcsh% echo $BASH_VERSION BASH_VERSION: Undefined variable.
- $DIRSTACK
在目录栈中最顶端的值。 (将会受到 pushd 和 popd 的影响)
这个内建变量与 dirs 命令相符, 但是 dirs 命令会显示目录栈的整个内容。 - $EDITOR
脚本所调用的默认编辑器, 通常情况下是 vi 或者是 emacs 。 - $EUID
“有效” 用户 ID 。
不管当前用户被假定成什么用户, 这个数都用来表示当前用户的标识号, 也可能使用 su 命令来达到假定的目的。
$EUID 并不一定与 $UID 相同。 - $FUNCNAME
当前函数的名字。(数组形式 $FUNCNAME[0] ) - $GLOBIGNORE
一个文件名的模式匹配列表,如果在通配(globbing)中匹配到的文件包含有这个列表中的某个文件, 那么这个文件将被从匹配到的结果中去掉。
- $GROUPS
目前用户所属的组。
这是一个当前用户的组 id 列表(数组), 与记录在 /etc/passwd 文件中的内容一样。
root# echo $GROUPS 0 root# echo ${GROUPS[1]} 1 root# echo ${GROUPS[5]} 6
- $HOME
用户的 home 目录, 一般是 /home/username - $HOSTNAME
hostname 放在一个初始化脚本中, 在系统启动的时候分配一个系统名字。 然而,
- gethostname() 函数可以用来设置这个 Bash 内部变量 $HOSTNAME 。
- $HOSTTYPE
主机类型
就像 $MACHTYPE , 用来识别系统硬件。
bash$ echo $HOSTTYPE i686
$IFS
内部域分隔符
这个变量用来决定 Bash 在解释字符串时如何识别域, 或者单词边界。
IFS默认为空白(空格,制表符,和换行符),但这是可以修改的,比如,在分析逗号分隔的数据文件时,就可以设置为逗号。注意IFS 默认为 空白(空格, 制表符,和换行符), 但这是可以修改的, 比如, 在分析逗号分隔的数据文件时, 就可以设置为逗号。 注意 * 使用的是保存在 $IFS 中的第一个字符。
$IGNOREEOF
忽略 EOF : 告诉 shell 在 log out 之前要忽略多少文件结束符(control-D)。
$LC_COLLATE
常在 .bashrc 或 /etc/profile 中设置, 这个变量用来控制文件名扩展和模式匹配的展开顺序。 如果 $LC_COLLATE 设置得不正确的话, LC_COLLATE 会在文件名匹配(filename globbing)中产生不可预料的结果。
$LC_CTYPE
这个内部变量用来控制通配(globbing)和模式匹配中的字符串解释。
$LINENO
这个变量用来记录自身在脚本中所在的行号。 这个变量只有在脚本使用这个变量的时候才有意义,并且这个变量一般用于调试目的。
$MACHTYPE
机器类型。标识系统的硬件。
bash$ echo $MACHTYPE i686
Bash 学习摘录2:https://developer.aliyun.com/article/1598579