bash变量类型:
环境变量,本地变量,局部变量,位置变量,特殊变量
环境变量: 作用域为当前shell及其子进程
export VARNAME=VALUE
或
VARNAME=VALUE
export VARNAME
本地变量: 作用域为当前shell进程
set VARNAME=VALUE
局部变量: 作用域为当前代码段
local VARNAME=VALUE
位置变量: 用于引用参数
$1,$2,$3...
shift
特殊变量: 用于保存特殊数据
$?: 保存上一个命令执行状态返回值
$#: 参数的个数
$*: 参数列表
$@: 参数列表
成功执行两个返回值:
执行结果:
执行状态(0-255): 正确执行为0,执行错误为1-255,其中1,2,127系统预留
输出重定向:
> : 覆盖重定向
>>: 追加重定向
2>: 错误重定向
2>>: 错误追加重定向
&>: 同时重定向
/dev/null: 软件设备, bit bucket
撤销变量:
unset VARNAME
查看变量:
set
查看当前shell中的环境变量:
printenv
env
export
bash中如何实现条件判断?
条件测试类型:
整数测试
字符测试
文件测试
条件测试的表达式:
[ expression ]: 命令测试法,表达式两边一定要有空格
[[ expression ]]: 关键字测试法
test expression
整数测试:
-eq: 测试两个整数是否相等; (e.g)[ $A -eq $B ]
-ne: 测试两个整数是否不等;
-gt: 测试两个整数是否大于关系
-lt: 测试两个整数是否小于关系
-ge: 大于或等于
-le:小于或等于
字符集合:[:digit:], [:lower:], [:upper:], [:punct:], [:space:], [:alpha:], [:alnum:]
字符测试:
==或=: =两边要有空格,不然会被识别为赋值
A=hello B=hi
(e,g) [ $A = $B ]
!=: 测试是否不相等
>
<
-n string: 测试指定字符串是否为空
-s string: 测试指定字符串是否不空
文件测试:
-e FILE: 测试文件是否存在, (e.g)[ -e /etc/inittab ]
-f FILE: 测试文件是否为普通文件
-d FILE: 测试指定路径是否为目录
-r FILE: 测试对当前用户指定文件是否有读权限
-w FILE: 测试对当前用户指定文件是否有写权限
-x FILE: 测试对当前用户指定文件是否有执行取权限
bash 技巧
bash -n xxx.sh 检查脚本语法
bash -x xxx.sh 检查脚本执行了哪些语句
脚本在执行时会启动一个子shell进程:
命令行中启动的脚本会继承当前shell环境变量
系统自动执行的脚本(非命令行启动)就需要自我定义需要各环境变量
命令的间逻辑关系:
逻辑与: &&
第一个条件为假时,第二条件不用再判断,最终结果已经有;
第一个条件为真时,第二条件必须得判断;
逻辑或: ||
如果用户user6不存在,就添加用户user6
! id user6 && useradd user6
id user6 || useradd user6
如果/etc/inittab文件的行数大于100,就显示好大的文件;
[ `wc -l /etc/inittab | cut -d' ' -f1` -gt 100 ] && echo "Large file."
变量名称:
1、只能包含字母、数字和下划线,并且不能数字开头;
2、不应该跟系统中已有的环境变量重名;
3、最好做到见名知义;
如果用户存在,就显示用户已存在;否则,就添加此用户;
id user1 && echo "user1 exists." || useradd user1
如果用户不存在,就添加;否则,显示其已经存在;
! id user1 && useradd user1 || echo "user1 exists."
如果用户不存在,添加并且给密码;否则,显示其已经存在;
! id user1 && useradd user1 && echo "user1" | passwd --stdin user1 || echo "user1 exists."
一,条件控制
###单分支的if语句
if 判断条件;then
statement1
statement2
...
if
###双分支的if语句
if 判断条件; then
statement1
statement2
...
else
statement3
statement4
...
fi
###多分支if语句
if 判断条件1; then
statement1
...
elif 判断条件2; then
statement2
...
elif 判断条件3; then
statement3
...
else
statement4
...
fi
###case语句:选择结构
case SWITCH in
value1)
statement
...
;;
value2)
statement
...
;;
*)
statement
...
;;
esac
a-z
A-Z
0-9
[abc]
二,循环控制
###Shell风格--for循环
for 变量 in 列表;do
循环体
done
for I in 1 2 3 4 ; do
循环体
done
生成for循环的列表
括号法生成法: {1..100}
seq生成法: `seq [起始数 [步进]] 结束数`
declare -i SUM=0
for I in {1..100};do
SUM=$[ $SUM+$I ]
done
echo "The SUM is: $SUM"
###C语言风格--for循环
for (( expr1 ; expr2 ; expr3 )); do
循环体
done
declare -i SUM=0
for ((J=1;J<100;J++));do
let SUM+=$J
done
###while循环
while循环:适用于循环次数未知的场景,要有退出条件
语法:
while CONDITION; do
statement
...
done
###until循环
进入循环:条件不满足
退出循环:条件满足
until CONDITION;do
statement
...
done
while得两种特殊用法:
(1)死循环
while :;do
done
(2)按行读取文件
while read LINE;do
echo $LINE
done < /path/to/somefile
# 如果一行中有空格、会分段打印
for line in `cat $FILE`;do
echo $line
done
###函数:
function FUNCNAME{
command
}
FUNCNAME {
command
}
自定义状态执行返回值:
return [0-255]
接受参数的函数:
FUNCNAME 5 6
$1: 5
$2: 6
shell中进行算术运算
1,let算数表达式
A=3 B=6
let C=$A+$B
echo $C
2,$[算术表达式]
D=$[$A+$B]
echo $D
3,$((算术表达式))
E=$(($A+$B))
echo $E
4,expr 算数表达式,表达式中各操作数及运算符之间要有空格,而且要用命令引用
F=`expr $A+$B`
echo $F
脚本练习:
shell中的计算保留精度
result=`echo "scale=2;111/22;" | bc`
echo $result
或
bc <<< "scale=2;111/22;"
组合测试条件
-a: 与关系
-o: 或关系
!: 非关系
if [ $# -gt 1 -a $# -le 3 ]
if [ $# -gt 1 ] && [ $# -le 3 ]
脚本练习:
判断当前主机的CPU生产商,其信息在/proc/cpuinfo文件中vendor id一行中。
如果其生产商为AuthenticAMD,就显示其为AMD公司;
如果其生产商为GenuineIntel,就显示其为Intel公司;
否则,就说其为非主流公司;
#!/bin/bash
#
cpu=`grep "vendor_id" /proc/cpuinfo | sed -r 's@[[:space:]]*@@g' | cut -d: -f2`
if [ "$cpu" = "AuthenticAMD" ];then
echo "Your CPU is AMD."
elif [ "$cpu" = "GenuineIntel" ];then
echo "Your CPU is Intel."
else
echo "Your CPU is UNKNOWN."
fi
脚本练习:
1、设定变量FILE的值为/etc/passwd,依次向/etc/passwd中的每个用户问好,并显示对方的shell,
形如:Hello, root, your shell: /bin/bash
并统计一共有多少个用户
#!/bin/bash
#
declare -i COUNT=0
FILE="/etc/passwd"
LINES=`wc -l /etc/passwd | cut -d' ' -f1`
for I in `seq 1 $LINES` ;do
UserName=`head -n $I $FILE | tail -n 1 | cut -d: -f1`
UserShell=`head -n $I $FILE| tail -n 1 | cut -d: -f7 |sed -r 's@^/.*/([^/]+)/?@\1@'`
echo "Hello, $UserName, your shell: $UserShell"
let COUNT=$COUNT+1
done
echo "The Mount Of User is $COUNT. "
2、添加10个用户user1到user10,密码同用户名;但要求只有用户不存在的情况下才能添加;
接受一个参数:
add: 添加用户user1..user10
del: 删除用户user1..user10
其它:退出
#!/bin/bash
#
if [ $# -lt 1 -o `whoami | id -u` -ne 0 ];then
echo "Please use root execute this shell-script.Usage: adminusers.sh [--add or --del]"
exit 2
fi
if [ "$1" = "--add" ];then
for I in {1..10}; do
( id -u "user$I" &> /dev/null && echo "user$I is exist." ) || ( useradd "user$I" &> /dev/null && echo "user$I" | passwd --stdin "user$I" &> /dev/null && echo "Add "user$I" Successfully.")
done
elif [ "$1" = "--del" ];then
for I in {1..10}; do
( userdel -r "user$I" >& /dev/null && echo "Delete "user$I" Successfully.")
done
else
echo "Unkown arg,try again."
exit 3
fi
数组的定义
何为数组?学过计算机编程语言的同学都知道,数组的特性就是一组数据类型相同的集合(不包括有一些编程语言提出来的关联数组的概念)。那么shell中数组是怎么定义的呢,我们来看两种数据类型:一是数值类型,二是字符串类型;虽然shell本身是弱类型的,但也可以这么区分。
数值类型的数组:一对括号表示数组,数组中元素之间使用“空格”来隔开。
举个列子:
arr_number=(1 2 3 4 5);
字符串类型数组:同样,使用一对括号表示数组,其中数组中的元素使用双引号或者单引号包含,同样使用“空格”来隔开。
arr_string=("abc" "edf" "sss"); 或者 arr_string=('abc' 'edf' 'sss');
数组的操作
我们使用数值类型数组arr_number=(1 2 3 4 5)做为源数组进行相关的讲解:获取数组长度,读取某个下标的值,对某个下标赋值,删除、分配和替换以及遍历。提一个知识点,我们在shell里面想获取某个变量的值,使用$符开头,如:$a或者${a}即可。
获取数组长度
arr_length=${#arr_number[*]}或${#arr_number[@]}均可,即形式:${#数组名[@/*]} 可得到数组的长度。
读取某个下标的值
arr_index2=${arr_number[2]},即形式:${数组名[下标]}
对某个下标赋值
这里需要提出两个问题:
第一个问题是如果该下标元素已经存在,会怎么样?
答:会修改该下标的值为新的指定值。
例如:arr_number[2]=100,数组被修改为(1 2 100 4 5)
第二个问题是如果指定的下标已经超过当前数组的大小,如上述的arr_number的大小为5,指定下标为10或者11或者大于5的任意值会如何?
答:新赋的值被追加到数组的尾部。
例如:arr_number[13]=13,数组被修改为(1 2 100 4 5 13)
删除操作
清除某个元素:unset arr_number[1],这里清除下标为1的数组;
清空整个数组:unset arr_number;
分片访问
分片访问形式为:${数组名[@或*]:开始下标:结束下标},注意,不包括结束下标元素的值。
例如:${arr_number[@]:1:4},这里分片访问从下标为1开始,元素个数为4。
模式替换
形式为:${数组名[@或*]/模式/新值}
例如:${arr_number[@]/2/98}
数组的遍历
数组遍历我们使用for语句来演示:
for v in ${arr_number[@]}; do
echo $v;
done
另一个例子
#!/bin/bash
declare -a serial
serial=(1 2 3 4)
PS3="Enter a number: "
select var in "a" "b" "c" "d"
do
if ! echo ${serial[@]} | grep -q $REPLY; then
echo "please enter [1-4]."
continue
fi
echo "your anwser is: $var"
break
done
备份地址: 【shell脚本语法】