bash编程
bash变量类型:
本地变量与局部变量
环境变量
特殊(系统)变量(bash内置,用来保存某些特殊数据的变量)
位置变量
本地变量:
animal=pig,作用域:当前整个bash进程
echo “there is some $(animal)s” “”是弱引用,做变量替换
echo ‘there is some $(animal)s’ ‘’是强引用,不做变量替换
局部变量:
local animal=pig,作用域:当前代码段
环境变量: export animal=pig,作用域:当前shell进程及其子进程
在命令提示符下执行任何一个脚本,都会启动一个子shell进程,会继承当前shell的环境变量
系统自动执行的脚本(非命令行启动)需要自我定义各种环境变量
特殊变量:
$?:上一个命令的执行状态返回值echo $?
$#:参数的个数
$*: 参数列表
$@:参数列表
$0:命令或脚本文件本身路径名称
位置变量:确定脚本的作用对象 $1 $2… 第一次参数 第二个参数
./filetest.sh /etc/fstab /etc/inittab
$1: /etc/fstab
$2: /etc/inittab
撤消变量:unset varname
查看当shell中变量:set
查看当前shell中的环境变量:printenv、env、export
/dev/null:软建模拟设备(软设备)bit bucket 数据黑洞
id broadon &> /etc/null 假设broadon存在,该用户的信息也不会显示在屏幕上,而是存到/etc/null中
shebang:魔数
file /bin/ls,可知其格式是elf可执行格式
编写的脚本文件是纯ascii码,得告诉内核这个文件是个脚本,让脚本解释器来执行shebang:魔数
#!/bin/bash 解释器的路径
bash first.sh 即使first.sh没有执行权限,但是这样却可以执行,明确指明bash这个解释器来执行解释这个脚本,此时的first.sh作为bash的参数来运行的。脚本执行完之后,脚本中的变量会被撤销掉的
条件测试类型:
整数测试
字符测试
文件测试
条件测试的表达式:
[ expression ] expression前后有空格
[[ expression ]] 是关键字
test expression
如:
int1=63
int2=77
[ $int1 -eq $ini2 ]
[[ $int1 -eq $int2 ]]
test $int1 -eq $int2
整数比较:
-eq: 测试两个整数是否相等;一样,执行状态返回值为0。比如 [ $a -eq $b ] echo $?
-ne: 测试两个整数是否不等;不等,为真;相等,为假;
-gt: 测试一个数是否大于另一个数;大于,为真;否则,为假;
-lt: 测试一个数是否小于另一个数;小于,为真;否则,为假;
-ge: 大于或等于
-le:小于或等于
字符测试:
==:测试是否相等,相等为真,不等为假 ==两边要有空格 [ $a == $b ]
!=: 测试是否不等,不等为真,等为假
>
<
-n string: 测试指定字符串是否为空,空则真,不空则假
-z string: 测试指定字符串是否不空,不空为真,空则为假
文件测试:
-e file:测试文件是否存在
-f file: 测试文件是否为普通文件
-d file: 测试指定路径是否为目录
-r file: 测试当前用户对指定文件是否有读权限;
-w file: 测试当前用户对指定文件是否有写权限;
-x file: 测试当前用户对指定文件是否有可执行权限;
[ -e /etc/inittab ]
[ -x /etc/rc.d/rc.sysinit ]
命令的间逻辑关系:
逻辑与: && 第一个条件为假时,第二条件不用再判断,最终结果已经有;第一个条件为真时,第二条件必须得判断;
逻辑或: ||
! id user2 && useradd user2 如果用户user2不存在,就添加用户user2,存在就不添加
id user6 || useradd user6
id broadon &> /etc/null && echo "hello" broadon用户存在就显示hello
[ `wc -l /etc/inittab | cut –d ' ' –f 1` -gt 100 ] && echo "large file." || echo “small file.”
! id user1 &> /dev/null && useradd user1 && echo "user1" | passwd --stdin user1 &> /dev/null || echo "user1 exists."
组合测试条件:
-a: 与关系
-o: 或关系
!: 非关系
if [ $# -gt 1 -a $# -le 3 ]
if [ $# -gt 1 ] && [ $# -le 3 ]
脚本编程:
顺序结构
选择结构if、case
循环结构for、while、until
选择结构if语句:
单分支if语句
if 判断条件; then
statement1
statement2
...
fi
双分支的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语句: switch 可以是0-9 a-z
case switch in
value1)
statement
...
;;
value2)
statement
...
;;
*)
statement
...
;;
esac
循环结构for语句:
for 变量 in 列表; do
循环体
done
for i in 1 2 3 4 5 6 7 8 9 10; do
加法运算
done
遍历完成之后,退出;其中列表可以是字符;
循环结构while语句:while循环适用于循环次数未知的场景,要有退出条件
while condition; do
statement
...
done
while的特殊用法一:
while :;do 死循环
done
while的特殊用法二:
while read line; do
done < /path/to/somefile
读取/path/to/somefile文件中的每一行,每循环读一行,把它放在line变量中
循环结构until语句:
until 条件;do
done
break: 提前退出循环
continue:提前结束本轮循环,而进入下一轮循环;
脚本编程之函数:function结构化编程,不能独立运行,需要调用时执行,可以被多次调用
定义一个函数:
function funcname {
command
}
funcname() {
command
}
调用funcname
自定义执行状态返回值: $?
return # return同exit一样,遇到就退出脚本0-255
引用函数执行结果 `funcname` 程序中的echo内容
接受参数的函数:
twoint 5 6 twoint为函数名
$1为5,$2为6
程序执行,可能有两类返回值:
程序执行结果
程序状态返回代码(0-255) echo $?
0: 正确执行
1-255:错误执行,1,2,127系统预留
“引用”一个命令的执行结果,要使用命令引用,比如:resaults=`wc -l /etc/passwd | cut –d : -f 1 `
使用一个命令的执行状态结果,要直接执行此命令,一定不能引用,比如: if id user1一句中的id命令就一定不能加引号;
如果想把一个命令的执行结果赋值给某变量,要使用命令引用,比如userid=`id -u user1`
如果想把一个命令的执行状态结果保存下来,并作为命令执行成功与否的判断条件,则需要先执行此命令,而后引用其状态结果,如
id -u user1
retval=$?
此句绝对不可以写为retval=`id -u user1`
对shell来讲,默认所有变量的值都是字符串,不能做运算
shell中如何进行算术运算:
a=3 b=6
1、let 算术运算表达式
let c=$a+$b
2、$[算术运算表达式]
c=$[$a+$b]
3、$((算术运算表达式))
c=$(($a+$b))
4、expr 算术运算表达式,表达式中各操作数及运算符之间要有空格,而且要使用命令引用 c=`expr $a + $b`
let i=0使i为数值,不加let默认为字符串
let i=$[$i+1]
sum=$[$sum+$i]
let sum+=$i
let i+=1 相当于 let i++
let i-=1 相当于 let i—
++i, --i *= /= %=
declare
-i sum=0:定义sum为整型
-x:定义为环境变量
数值型(整型、浮点型)、字符型:bash不支持浮点型
exit:提前退出脚本
exit(数字) 0表示正确 1-255错误
如果没有指定退出状态码,最后执行的一条命令的状态码即是脚本的状态码,用echo $?查看
bash:
-n:文件测试脚本是否有语法错误
-x:单步执行
echo “scale=2;111/22;” | bc
bc << “scale=2;111/22;”
{1..100}:自动展开
seq [起始数] [步进长度] 结束数 在for中生成列表,要用命令替换,如for I in `seq 1 10`;do
shift把传进去的参数去掉
read name:从键盘输入的数据保存变量name中
如果变量只有一个,输入的全部赋给变量,变量有两个,输入的只有一个,输入的给第一个变量,第二个没有赋值。变量少于输入的,前面的一一对应,多余的全给最后一个变量
read -p “input two integers” a b
read –t 5 -p “input two integers” a b 时间限制
数组
变量是命名的内存空间,在里面可以存储值,通过变量名来引用。使用一片连续的内存空间来存储多个同一类型的变量称为数组。
定义:array =(1 2 3 4 5) 一对括号表示是数组,数组元素用“空格”符号分割开。
declare -a申明a为数组
echo $array 输出1
用${#数组名[@或*]} 可以得到数组长度,如for ((i=0;i<${#array[@]};i++))遍历数组
echo ${#array_name}第一个元素的字符长度
用${数组名[下标]} 下标是从0开始 下标是:*或者@ 得到整个数组内容,如${array[*]}
直接通过数组名[下标] 就可以对其进行引用赋值,如果下标不存在,自动添加新一个数组元素
直接通过:unset 数组[下标] 可以清除相应的元素,不带下标,清除整个数据。
直接通过 ${数组名[@或*]:起始位置:长度} 切片原先数组,返回是字符串,中间用“空格”分开,因此如果加上”()”,将得到切片数组
调用方法是:${数组名[@或*]/查找字符/替换字符} 该操作不会改变原先数组内容