变量:命名的内存空间:不同类型数据存储空间不一样; 数据存储方式: 字符:1 如:1 既是字符又是数值;110,24 这种编码字符集美国成为ASCII 数值:1,110 --> 0-255 之类,将十进制转成二进制,八位就够了,就是一个字节; 整型数值和浮点型数值;存储一个汉字需要许多的0 和1 来存入到计算机; 计算机内存最小存储单位为字节 1字节=8位;统一标准:字符集 来对应中文汉字或者其他语言;如 gbk;gb18030;utf8;否则会乱码;英文是127个变换,一个字节足以; 数值:110+12=122 ,11010=1100 字符运算:110+12=11012,11010=110110110110110110十次 变量:变量类型 作用:1、数据存储格式;2、参与的运算;3、表示的数据范围; 类型:字符;数值(整型(int)和浮点型(float)) 编程程序语言:强类型 弱类型:bash :把所有的要存储的数据通通充当字符进行;不支持浮点型; 布尔型 逻辑运算:true,false 非 异或 与 : 1&&1 =1 ;1&&0=0;0&&1=0; 0&&0=0 或:1||1=1; 1||0=1; 0||1=1; 0||0=0 非: !1=0; !0=1 异或:两个同时为真为假,两个为假为真; 短路运算: 与: 对于与运算,对于左侧是0,结果必定是0;第一个为1,第二个必须参与运算; 或: 第一个为1,结果必定为1;第一个为0,第二个必须要参与运算; 比如: ls /var&&echo “hello” 如果第一个是成功的,第二个命令必须得运行; 第一个运行失败了,第二个直接不运行了,短路运算; ls /var||echo “hello”第一个成功,第二个不需要执行;第一个失败,执行第二个; ls /var&&echo “success”||echo “failure”第一个成功,直接返回;第一个失败,就执行第二个。 id root &> /dev/null &&echo “exits”||echo “no such user” 小结:shell基础特性,grep Shell: #!/bin/bash 过程式:以命令为中心 对象式:以数据为中心 grep:j文本过滤器(支持正则) PATTERN(魔数) REGEXP(正则) BRE(基本正则),ERE(扩展正则) BRE:字符匹配:‘.’(任意单个字符); ‘[]’(范围内任意单个字符); ‘[^]’ (范围外任意单个字符); 次数匹配:‘’,匹配前面的字符任意次;’(\是转义)?’:匹配前面字符0或者1次,可有可无;+:匹配前面字符至少一次;{m}精确指定次数。 位置锚定: ^:行首指定 :指定模式的最左侧 $:行尾指定:指定模式的最右侧 ^patterns:用于模式匹配整行; ^$:空行; ^[[:space:]]$: 空白行 < 或者 \b:词首锚定:用于单词模式的左侧; > 或者 \b词尾锚定:用于单词模式的右侧; <PATTERN>:匹配整个单词; 分组符号 () (xy) grep ‘(xy)+’grep.txt grep ‘xy+’grep.txt X后面至少跟一个y NOtice:分组括号中的模式匹配到的内容会被正则表达式引擎记录于内部的变量中,这些变量的命名方式为:\1,\2,\3..... \1:从左侧起,第一个左括号以及与之匹配右括号之间的模式所匹配到的字符; (ab+(xy)); \1:ab+(xy) \2: xy
后向引用:引用前面的分组括号中的模式所匹配字符,(而非模式本身) grep '([[:alpha:]]{1,3}t>).*\1' /etc/passwd Vim,sed,awk,grep ,nginx bash 脚本编程: 过程式编程语言: 顺序执行 选择执行 循环执行
选择执行: if 判断条件;then (单分支if) 条件为真的分支代码 结束
if 判断条件;then (双分支if) 条件为真的分支代码 else 条件为假的分支代码 fi
vi adduser.sh #!/bin/bash if [ $# -lt 1 ];then echo "at least one argument."
if id $1 &> /dev/null;then echo "$1 exists." else useradd $1 [ $? -eq 0 ]&& echo "$1" |passwd --stdin $1 &> /dev/null fi 多分支: if condition;then If-true Elif condition;then If-true Elif condition;then If-true ...... Else All-false Fi 逐条件进行判断:第一次遇到“真”条件时,执行其分支,而后结束; 示例:用户键入文件路径,脚本来判断文件类型; #!/bin/bash read -p “Enter a file path: ”filename if
bash编程之for循环 for 变量名 in 列表; do(跟if 的then 相似,换行“;”可以省略) 循环体 done 执行机制: 依次将列表中的元素赋值给"变量名",每次赋值后即执行一次循环体;直到列表中的元素耗尽,循环结束; 示例:添加10个用户,user1---user3,密码同用户名; #!/bin/bash if [ ! $UID -eq 0 ];then echo "only root." exit 1 fi for username in user1 user2 user3;do if id $username &> /dev/null;then echo "$username exists." else useradd -M $username if [ $? -eq o ];then echo "$username"|passwd --stdin $username &> /dev/null echo "Add $username finished." fi fi
#!/bin/bash if [ ! $UID -eq 0 ];then echo "only root." exit 1 fi for i in {1..10};do if id user$i &> /dev/null;then echo "user$i exists." else useradd -M user$i if [ $? -eq o ];then echo "user$i"|passwd --stdin user$i &> /dev/null echo "Add user$i finished." fi fi
列表生成方式: (1)直接输出列表; (2)整数列表; (a)in {首数..尾数}(in {1..10}) (b)$(seq [start [step]] end) (3)返回列表的命令 $(COMMAND) (4)glob (b)变量引用 $@,$*
示例:判断某路径下所有文件的类型;
#!/bin/bash
for file in $(ls /var);do (/var/*)
if [ -f /var/$file ];then
echo "common file."
elif [ -L /var/$file ];then
echo "Symbolic file."
elif [ -d /var/$file ];then
echo "Directory."
else
echo "Other type."
fi
done
查看tcp状态脚本 netstat -tan |grep "^tcp>/"|awk "{print $NF}"
#!/bin/bash estab=0 listen=0 other=0
for status in $(netstat -tan |grep "^tcp>/"|awk "{print $NF}");do if [ "$status" == "ESTABLISHED" ];then let estab++ elif [ "$status" == "LISTEN" ];then let listen++ else let other++ fi done echo "ESTABLISHED: $estab" echo "LISTEN: $listen" echo "Unkown: $other"
练习1:/etc/rc.d/rc.d目录下分别有多个以K开头和以S开头的文件;分别读取每个文件,以K开头的文件输出为文件名加stop,以S开头的文件输出为文件名加start; #!/bin/bash for file in /etc/rc.d/rc.d/*;do
bash编程之while循环 顺序执行 选择执行 条件测试 运行命令或[[ expression ]] 执行状态返回值: If Case 循环执行 将某代码段重复运行多次; 重复运行多少次? 循环次数事先已知: 循环次数事先未知: 必须有进入和退出条件: For, while,until 函数:结构化编程及代码重用; function For 循环语法: For NAME in list; do 循环体 Done 列表生成方式: (1)整数列表 {start..end} $(seq start [[step]end]) (2) glob /etc/rc.d/rc3.d/K* (3)命令 Bash -n 判断脚本正确性;bash -x 查看脚本执行流程; 示例: 监测10.0.27.1-20的网络状态 #!/bin/bash
net="10.0.27" uphosts=0 douwnhosts=0 for i in {1..21};do ping -c 1 -t 1 ${net}.${i} &> /dev/null if [ $? -eq 0 ];then echo "${net}.${i} is up" let uphosts++ else echo "${net}.${i} is down" let downhosts++ fi done echo "UP hosts: $uphosts" echo "Down hosts: $downhosts"
While 循环: While CONDITION;do 循环体 Done CONDITION:循环控制条件 CONDITION::循环控制条件:进入循环之前,先做一次判断;每一次循环之后会再次做判断; 条件为“true”,则执行一次循环;直到条件测试状态为false中止循环; 因此CONDITION一般应该有循环控制变量;而此变量的值会在循环体不断被修正; 示例:求100以内所有正整数之和; #!/bin/bash sum=0 i=1 while [ $i -le 100 ];do let sum+=$i let i++ done echo “$i” echo “summary: $sum”
练习:用while批量添加用户use1---user10; For与while区别就是 while 要手动控制循环 练习:打印九九乘法表:(分别使用for和while循环实现)
bash脚本编程:
While CONDITION;do
循环体
Done
进入条件:CONDITION为True
退出条件:false
Until CONDITION;do
循环体
Done
进入条件:false
退出条件:true
示例:求100以内所有正整数之和;
For:
#!/bin/bash
sum=0
i=1
for i in {1..100};do
let sum+=$i
done
echo "$i"
echo "$sum"
While:
#!/bin/bash
sum=0
i=1
while [ $i -le 100 ];do
sum=$[$sum+$i]
let sum+=$i let i++ done echo "$i" echo "$sum"
Until: #!/bin/bash i=1 sum=0 until [ $i -gt 100 ];do let sum+=$i let i++ done echo "$i" echo "$sum"
利用until打印九九乘法表 #!/bin/bash j=1 i=1 until [ $j -gt 9 ];do until [ $i -gt $j ];do echo -n -e "${i}X${j}=$[$i*$j]\t" let i++ done echo let i=1 let j++ done
循环控制语句(用于循环体中):
Countiue
Continue [N] 提前结束第N层的本轮循环,并直接进入下一轮判断;
While CONDITION1;do
CMD1
......
If CONDITION2;then
Continue
Fi
CMDn
....
done
Break
Break [n] 提前结束循环
CMD1
......
If CONDITION2;then
Brrak
Fi
CMDn
....
done
示例:求100以内所有偶数之和:要求遍历100以内的所有正整数;
#!/bin/bash
i=0
sum=0
until [ $i -gt 100 ];do
let i++
if [ $[$i%2] -eq 1 ];then
continue
fi
let sum+=$i
Done
;
While true;do
循环体
Done
示例2:用户选择,并显示完成后不退出脚本,而是提示用户继续选择显示其他内容:直接使用quit退出; #!/bin/bash cat <<EOF cpu)show cpu information; mem)show memory information; disk)show disk information; quit)quit ################################# EOF if [ $UID -gt 0 ];then echo "Command mast be root."&& exit 1 fi
read -p "Enter a option: " option while [ "$option" != "cpu" -a "$option" != "mem" -a "$option" != "disk" -a "$option" != "quit" ];do read -p "Wrong option!! Enter again: " option done if [ "$option" == "cpu" ];then lscpu elif [ "$option" == "mem" ];then cat /proc/meminfo elif [ "$option" == "disk" ];then fdisk -l else echo "Quit" fi 示例2:每隔三秒到系统上获取已登录的用户的信息:
条件判断:case语句
Case 变量引用 in
PAT1)
分支1
;;
PAT2)
分支2
;;
....
*)
默认分支
;;
Esac
#!/bin/bash cat <<EOF cpu)show cpu information; mem)show memory information; disk)show disk information; quit)quit ################################# EOF if [ $UID -gt 0 ];then echo "Command mast be root."&& exit 1 fi
read -p "Enter a option: " option while [ "$option" != "cpu" -a "$option" != "mem" -a "$option" != "disk" -a "$option" != "quit" ];do read -p "Wrong option!! Enter again: " option done case "$option" in cpu) lscpu ;; mem) cat /proc/meminfo ;; disk) fdisk -l ;; *) echo "Quit...." exit 0 esac
练习:写一个脚本,完成 如下需求; (1)脚本可接收参数:start,stop,restart,status; (2)如果参数非此四者之一,提示使用格式后报错推出; (3)如果是start:则创建/var/lock/subsys/SCRIPT_NAME,并显示“启动成功” (4)如果是stop:则删除/var/lock/subsys/SCRIPT_NAME,并显示“停止完成”;考虑:如果事先已然停止过了,该如何处理? (5)如果是restart ,则先stop,再start; 考虑:如果本来没有start,如何处理; (6)如果是status,则 如果/var/lock/subsys/SCRIPT_NAME文件存在,则显示“SCRIPT_NAME is running...”; 如果/var/lock/subsys/SCRIPT_NAME文件存在,则显示“SCRIPT_NAME is stopped...”; 其中:SCEIPT_NAME为当前脚本名;