bash的基础特性(4)
目录
一、bash的变量
变量类型
3个作用(规定了) 数据存储格式、存储空间大小、参与运算种类
字符型
数值型:整型、浮点型
强类型:定义变量时必须指定类型、参与运算必须符合类型要求;调用未声明变量会产生错误
弱类型:无须指定类型,默认均为字符型
参与运算会自动进行隐式类型转换
变量无须事先定义可直接调用
变量命名法则
不能使程序中的保留字:例如if, for
只能使用数字、字母及下划线,且不能以数字开头
见名知义
bash中的变量的种类
根据变量的生效范围等标准分类
本地变量:生效范围为当前shell进程
对当前shell之外的其它shell进程,包括当前shell的子shell进程均无效
环境变量:生效范围为当前shell进程及其子进程
局部变量:生效范围为当前shell进程中某代码片断(通常指函数)
在某函数生命周期时有效
位置变量:调用通过命令行传递给它的参数,用$1, $2, ... 来表示,用于让脚本在脚本代码中
特殊变量:$?, $0, $*, [email protected], $#
1.本地变量
变量赋值:name='value'
可以使用引用,value可以是:
① 可以是直接字串:name="username"
② 变量引用: name="$username" ,如果username中没有空个则可以不添加双引号 name=$username
③ 命令引用: name=`COMMAND` ,在` `中注意不要多添加$
name=$(COMMAND)
P.S. echo name
变量引用:${name}, $name
"":弱引用,其中的变量引用会被替换为变量值
'':强引用,其中的变量引用不会被替换为变量值,而保持原字符串
命令:set 显示已定义的所有变量
命令:unset name 销毁变量
2.环境变量
变量声明、赋值: export name=VALUE
declare -x name=VALUE 定义环境变量
把变量导出到环境变量
变量引用:${name}, $name
命令:export, env, printenv 显示所有环境变量
命令:unset name 销毁变量
命令:pstree 显示进程树
问题:bash有哪些内建的环境变量?
SHELL, UID, PS1, HOME
PATH, PWD, OLD
HISTSIZE, HISTFILE
... ...
PS1 定义了命令提示符前的内容
只读变量 read only
类似于常量,不能修改和撤销
命令:readonly name
命令:declare -r name
3.位置变量
在脚本代码中调用通过命令行传递给脚本的参数
$1, $2, ...:对应调用第1、第2等参数
4.特殊变量
$?:上条命令的执行状态结果
$0:命令本身
$*:传递给脚本的所有参数,所有参数当一个字符串
[email protected]:传递给脚本的所有参数,把每一个参数当成独立字符串
$#:传递给脚本的参数的个数
(脚本)判断给出的文件的行数
#!/bin/bash
LineCount="$(wc -l $1| cut -d' ' -f1)"
echo "$1 has $LineCount lines."
命令:shift [n]
二、bash的配置文件
1.按生效范围划分
全局配置:
/etc/profile()登录Shell的时候读取
/etc/profile.d/*.sh
/etc/sysconfig/i18n
/etc/bashrc
/etc/profile(交互式登录的shell才会读取)
设置的主要变量有PATH, MAIL, USER, HOSTNAME, HISTSIZE
/etc/profile.d/*.sh(可通过创建.sh文件设置共享的命令别名)
/etc/sysconfig/i18n(由/etc/profile.d/lang.sh调用,主要设置变量LANG)
/etc/bashrc(非交互式登录的shell读取)
定义了:依据不同UID规定umask, 提示符(PS1变量),调用/etc/profile.d/*.sh
个人配置:
~/.bash_profile
~/.bashrc
~/.bash_profile(交互式登录的shell才会读取)
在bash读取完/etc/parofile及其调用的其他配置文件后,读取~/.bash_profile,可设置PATH,通过export PATH将其设置为环境变量
~/.bashrc(非交互式登录的shell读取)
由于~/.bashrc文件会调用/etc/bashrc,所以如果没有~/.bashrc,则bash提示符会变成类似于:-bash-3.2$,解决办法,复制/etc/skel/.bashrc到家目录下,再source ~/.bashrc
2.按功能划分
profile类:主要为交互式登录的shell提供配置
全局:/etc/profile, /etc/profile.d/*.sh
个人:~/.bash_profile
作用:
①用于定义环境变量
②运行命令或脚本
bashrc类:主要为非交互式登录的shell提供配置
全局:/etc/bashrc
个人:~/.bashrc
作用:
①定义命令别名
②定义本地变量
命令:读入环境配置文件source /path/to/config_file
或 . /path/to/config_file
shell登录
交互式登录: ①直接通过终端输入账号密码登录
②使用“su - UserName”或“su -l UserName”切换的用户
读取顺序
/etc/profile --> /etc/profile.d/*.sh --> ~/.bash_profile --> ~/.bashrc --> /etc/bashrc
非交互式登录: su UserName
图形界面下打开的终端
执行脚本
读取顺序
~/.bashrc --> /etc/bashrc --> /etc/profile.d/*.sh
编辑配置文件定义的新配置的生效方式
① 重新启动shell进程
② 使用source或.命令进程
问题: a. 在哪个配置文件可以定义对所有用户都生效的别名?
/etc/bashrc
b. 在哪个配置文件可以定义对所有用户都生效的登陆提示?
/etc/profile.d/*.sh
c. 在哪个配置文件设置可以让用户的PATH环境变量的值多出一个路径,例如多如/usr/local/apache2/bin
仅对管理员 export PATH="$PATH:/usr/local/apache2/bin"
/root/.bashrc
对所有 /etc/bashrc 在/etc/profile.d/下创建一个内容为export PATH="$PATH:/usr/local/apache2/bin"的.sh名结尾的文件
三、bash的算术运算
相关运算符
+, -, *, /, %, **
&, &&, |, ||, !
1.实现算术运算的方式
① let var=算术表达式,*不需要转义
② var=$[算术表达式] ,*不需要转义
③ var=$((算术表达式)) ,*不需要转义
④ var=$(expr arg1 arg2 arg3 ...),*需要转义
乘法符号有些场景中需要转义
bash有内建的随机数生成器:$RANDOM
2.增强型赋值
+=, -=, *=, /=, %=
let var OPER value
e.g. let count+=1
自增,自减
let var+=1
let var++
let var-=1
let var--
练习
①(脚本)计算/etc/passwd文件中的第10个用户和第20用户的ID之和
#!/bin/bash
userid1=$(head -n 10 /etc/passwd | tail -n 1 | cut -d:-f3)
userid2=$(head -n 20 /etc/passwd | tail -n 1 | cut -d:-f3)
useridsum=$[$userid1+$userid2]
echo "uid sum:$useridsum"
②(脚本)传递两个文件路径作为参数给脚本,计算这两个文件中所有空白行之和
#!/bin/bash
spaceline1=$(grep "^[[:space:]]*$" $1 | wc -l)
spaceline2=$(grep "^[[:space:]]*$" $2 | wc -l)
echo "The sum of space line:$[$spaceline1+$spaceline2]"
③统计/etc, /var, /usr目录共有多少个一级子目录和文件
四、bash的条件测试
条件测试:
判断某需求是否满足,需要由测试机制来实现
P.S. 专用的测试表达式需要由测试命令辅助完成测试过程
测试方式
test EXPRESSION
[ EXPRESSION ]
[[ EXPRESSION ]]
Note:EXPRESSION前后必须有空白字符
测试表达式的类别
1.数值测试
-gt:是否大于
-ge:是否大于等于
-eq:是否等于
-ne:是否不等于
-lt:是否小于
-le:是否小于等于
2.字符串测试
==:是否等于 也可以用=
P.S. ==号两边要有空格,否则会被识别成赋值
>:是否大于
<:是否小于
!=:是否不等于
=~:左侧字符串是否能够被右侧的PATTERN所匹配,测试条件的组合
Note:此表达式一般用于[[ ]]中
-z "STRING":测试字符串是否为空,空则为真,不空则为假
-n "STRING":测试字符串是否不空,不空则为真,空则为假
Note:用于字符串比较时的用到的操作数都应该使用引号
P.S. 模式匹配可以不用全串匹配,e.g. ^t部分匹配tudou也执行成功
3.文件测试
①存在性测试
-a FILE:文件存在性测试
-e FILE:文件存在性测试,存在为真,否则为假
②存在性及类别测试
-b FILE:是否存在且为块设备文件
-c FILE:是否存在且为字符设备文件
-d FILE:是否存在且为目录文件
-f FILE:是否存在且为普通文件
-h FILE 或 -L FILE:存在且为符号链接文件
-p FILE:是否存在且为命名管道文件
-S FILE:是否存在且为套接字文件
问题:为什么要做文件测试?
写脚本时,事先判断某个文件在不在,再才进行后续操作
③文件权限测试
取决于当前用户
-r FILE:是否存在且可读
-w FILE:是否存在且可写
-x FILE:是否存在且可执行
④文件特殊权限测试
-g FILE:是否存在且拥有sgid权限
-u FILE:是否存在且拥有suid权限
-k FILE:是否存在且拥有sticky权限
⑤文件大小测试
-s FILE:是否存且非空
⑥文件是否打开
-t fd:fd表示文件描述符是否已经打开且与某终端相关
-N FILE:文件自动上一次被读取之后是否被修改过
-O FILE:当前有效用户是否为文件属主
-G FILE:当前有效用户是否为文件属组
⑦双目测试
FILE1 -ef FILE2:FILE1与FILE2是否指向同一个设备上的相同inode
nt:new than ot:old than
FILE1 -nt FILE2:FILE1是否新于FILE2
FILE1 -ot FILE2:FILE1是否旧于FILE2
P.S. 备份时用到
e.g. [ -e /tmp/test ] || mkdir /tmp/test
4.组合测试条件
第一种方式:
COMMAND1 && COMMAND2
COMMAND1 || COMMAND2
! COMMAND
e.g. [ -e FILE ] && [ -r FILE ]
第二种方式:
EXPRESSION1 -a EXPRESSION2
EXPRESSION1 -o EXPRESSION2
! EXPRESSION
P.S. 必须使用测试命令进行,即test, [ ] [[ ]]
五、bash自定义退出状态码
命令:exit [n]:自定义退出状态码
注意: 脚本中一旦遇到exit命令,脚本会立即终止;终止退出状态取决于exit命令后面的数字n
如果未给脚本指定退出状态码,整个脚本的退出状态码取决于脚本中执行的最后一条命令的状态码
练习
(脚本)接受一个文件路径作为参数
如果参数个数小于1,则提示用户“至少应该给一个参数”,并立即退出
如果参数个数不小于1,则显示第一个参数所指向的文件中的空白行数
#!/bin/bash
[ $# -lt 1 ] && echo "至少给一个参数" && exit 2 || echo " The space line is $(grep "^$" $1 | wc -l)"
#!/bin/bash
[ $# -lt 1 ] && (echo "please input a arge" && exit ) || echo "`grep "^$" $1 | wc -l`"
回顾
命令:set, unset,export, declare, env, printenv, pstree, readonly, shift
配置文件:profile, bashrc
算术运算:
let, $[], $(()), expr
+=, -=, *=, /=
++, --
条件测试:test, [], [[]]
三种:
数值:-lt, -le, -gt, -ge, -ne, -eq
字符串:==, !=, >, <, =~, -z, -n
文件
单目:-e, -f, -d, -b, -c, -L, -P, -S, -r, -w, -x, -s
双目:-nt, -ot
组合测试:-a, -o, !
自定义退出码:
exit [n]
参考资料:
马哥随堂笔记
注:诚恳欢迎读者对本文提出批评意见,若发现存在错误,我定第一时间修改。如果读者觉得文章对您有帮助,欢迎点赞鼓励一下哟٩(๑❛ᴗ❛๑)۶。