在bash shell脚本中,咱们要先了解三种执行顺序git
顺序执行 (从左到右,从上到下的执行)shell
选择执行 (条件知足或者不知足的时候,才会执行某段结构)
express
循环执行 (重复执行某段结构)vim
今天所写的if 就是选择顺序,for就是循环执行bash
在if或者for中不可避免的要使用一些结构,还有一些运算方法,我先把这些列出来,方便之后使用。ide
算术运算方法:命令行
1.$[expression]内存
其中的表达式能够是纯数字组成的,也可使用变量引用变量值;在使用变量时,能够将$符号省略;资源
示例:字符串
# echo $[3+4]
# NUM1=5 ; NUM2=4 ; echo $[NUM1*NUM2]
2.let VAR=EXPRESSION
根据算术表达式完成算术运算并赋值给指定的变量;
3.$((EXPRESSION))
其中的表达式能够是纯数字组成的,也可使用变量引用变量值;在使用变量时,能够将$符号省略;
4.expr ARGU1 ARGU2 ARGU3
其中ARGU1和ARGU3必须是整数数值;ARGU2是算术运算符;
5.echo "EXPRESSION" | bc
6.bc <<< EXPRESSION
位置参数变量:
$0:命令的自己,对于脚本而言,就是该脚本的路径;
$1,$2.....$n:脚本后面经过命令行给脚本传递的命令行参数;
n>9时,引用该位置变量时,须要加{},即${10}
特殊变量:
$@:给出的全部位置参数的列表,当使用双引号引用时,每一个参数做为单独的字符串存在;
$*:给出的全部位置参数的列表,当使用双引号引用时,整个参数列表被当作一个字符串;
$#:标识除去$0以外,整个命令行中有多少个参数;
shift命令,能够将$2->$1;
if语句:
if: if 命令; then 命令; [ elif 命令; then 命令; ]... [ else 命令; ] fi
if语句的单分支结构:
if 命令; then 命令; fi
注意:是否会执行then后面的命令,取决于if后面的命令的执行状态返回值;
1.若是其返回值为真,则执行then后面的命令;
2.若是其但回执为假,则不执行then后面的命令;
建议在脚本中的书写格式:
if CONDITION ; then
STATEMENT
..
fi
或
if CONDITION ;
then
STATEMENT
..
fi
if语句的双分支结构:
if 命令; then 命令; else 命令; fi
注意:是否会执行then或else后面的命令,取决于if后面的命令的执行状态返回值;
1.若是其返回值为真,则执行then后面的命令;
2.若是其但回执为假,则执行else后面的命令;
建议在脚本中的书写格式:
if CONDITION ; then
STATEMENT
..
else
STATEMENT
..
fi
或
if CONDITION ;
then
STATEMENT
..
else
STATEMENT
..
fi
if语句的多分支结构:(不建议使用,太麻烦,咱们能够用下边的方法,进行单个或者多个的嵌套解决)
if 命令; then 命令; [ elif 命令; then 命令; ]... [ else 命令; ] fi
注意:是否会执行then或else后面的命令,取决于if后面的命令的执行状态返回值或者elif后面的命令的执行状态返回值;
1.首先判断if后面的命令的状态返回值是否为真,若是为真,就执行then后面的语句;若是为假,就继续判断第一个elif后面的命令的执行状态返回值;
2.第一个elif后面的命令的执行状态返回值为真,就执行第一个elif语句中then后面的命令,不然,就继续判断第二个elif后面的命令执行状态返回值;
3.以此类推,会判断每一个elif后面的命令的执行状态返回值是否为真,若是全部的if和elif后面的命令的执行状态返回值均为假,则执行else后面的语句;
建议在脚本中的书写格式:
if CONDITION ; then
STATEMENT
..
elif CONDITION2 ; then
STATEMENT
..
else ; then
STATEMENT
..
fi
或
if CONDITION ;
then
STATEMENT
..
elif CONDITION2 ; then
STATEMENT
..
else
STATEMENT
..
fi
注意:if的多分支结构,使用场景很少,并且有些时候,可使用嵌套的单分支或双分支if结构代替if多分支结构;
嵌套的if结构:
if CONTITIONG1 ; then
if CONTITIONG2 ; then
if CONTITIONG3 ; then
STATEMENT
..
else
STATEMENT
fi
else
STATEMENT
fi
else
STATEMENT
fi
一个好的循环结构,必须包括两个重要的环节;
1.进入循环的条件:
在符合要求或知足条件时才开始循环;
2.退出循环的条件:
达到某个要求或符合某个条件时须要结束或终止循环的执行;
for循环:
1.遍历列表的循环:
为列表中的每一个成员执行命令。
for 名称 [in 词语 ... ] ; do 命令; done
建议在脚本中书写的格式:
for VAR_NAME in LIST ; do
循环体
done
或
for VAR_NAME in LIST
do
循环体
done
注意:
VAR_NAME:任意指定的变量名称,变量的值是从LIST中遍历获取的各个元素;
LIST:for循环须要遍历的列表;能够经过如下方式生成列表;
1.直接给出列表;
2.纯整数列表;
1)花括号展开:
{FIRSTNUM..LASTNUM}
{FIRST,SECOND,THIRD,...,LAST}
2)seq命令
seq [OPTION]... LAST
seq [OPTION]... FIRST LAST
seq [OPTION]... FIRST INCREMENT LAST
3.花括号展开:
{FIRST..LAST}
4.命令的执行结果:
ls /etc
5.GLOBBING通配符
6.某些特殊变量的值:
$*,$@
循环体:
通常来讲,循环体中应该可以用到VAR_NAME变量的值的命令或命令的组合;若是循环体中的命令并无用到VAR_NAME变量的值的话,列表的元素个数,就是这次for循环的次数;
1.进入循环的条件,LIST中尚有未被取尽的元素;
2.退出循环的条件,LIST中的元素被取尽;
3.for循环几乎不会出现死循环;
4.在执行循环的过程当中,须要将整个LIST载入内存,所以。对于大列表来讲,可能会消耗比较多的内存及CPU资源;
简单的例子(vim编辑内容)
1.传递一个字符串给脚本,脚本会将该字符串看成用户名,若是该用户不存在,则添加之并为其设置与用户名相同的密码。
#!/bin/bash # if [ $# -ne 1 ] ; then echo "please input one name charast" exit 6; fi if id $1 &> /dev/null ; then echo "This user already exists" else useradd $1 &> /dev/null echo $1 | passwd --stdin $1 &> /dev/null echo "This user creat and password is username" fi
2.将两个文本文件的路径传递给脚本做为其参数,若是有文件不存在,则结束脚本执行并报告错误信息;若是文件都存在,则比较两个文件中哪一个文件的行数多,返回行数多的文件的文件名。
#!/bin/bash # read -p "Please input two files: " FILE1 FILE2 if ! cat $FILE1 &> /dev/null ; then echo "please enter the first true path file" exit 5 if ! cat $FILE2 &> /dev/null ;then echo "please enter the second true path file" exit 5 fi fi LINE1=$(cat $FILE1 | wc -l ) LINE2=$(cat $FILE2 | wc -l ) if [ $LINE1 -ne $LINE2 ] ; then if [ $LINE1 -gt $LINE2 ] ; then echo "$FILE1" else echo "$FILE2" fi else echo "$FILE1 and $FILE2 are generally long" fi unset FILE1 FILE2 LINE1 LINE2
3.利用RANDOM变量随机生成十个数字,显示出这十个数字,并显示出其中的最大值和最小值。
#!/bin/bash # touch /tmp/math.txt for I in $(seq 1 10) ; do J=$RANDOM echo "$J " echo "$J" >> /tmp/math.txt done K=$( sort -n /tmp/math.txt | head -1) L=$( sort -n /tmp/math.txt | tail -1) echo "laster $L ; leaster $K " rm -rf /tmp/math.txt exit 5
4.给脚本传递一个数字做为行总数,分别打印由*组成的最0小锐角朝上和朝下的等腰三角形以及菱形。
#!/bin/bash # read -p "enter one number: " INT if [[ $INT =~ [^[:digit:]] ]] ; then echo "please enter the number" exit 5 fi echo ”zheng sanjiao“ for I in $(seq $INT) ; do for J in $(seq $[INT-I]) ; do echo -n " " done for K in $(seq $[2*I-1]) ; do echo -n "*" done echo done echo "dao sanjiao" for M in $(seq $INT) ; do for B in $(seq $[M-1]) ; do echo -n " " done for N in $(seq $[2*(INT-M)+1]) ; do echo -n "*" done echo done echo "lingxing" if [ $[INT%2] -ne 0 ] ; then INT2=$[(INT+1)/2] for Q in $(seq $INT2) ; do for W in $(seq $[INT2-Q]) ; do echo -n " " done for E in $(seq $[2*Q-1]) ; do echo -n "*" done echo done for R in $(seq $[INT2-1]) ; do for T in $(seq $[R]) ; do echo -n " " done for Y in $(seq $[2*(INT2-R)-1]) ; do echo -n "*" done echo done exit 7 else echo "qing shuru jishu >3" fi
5.分别打印顺序和旋转的九九乘法表。
顺序的九九乘法表是正常的九九乘法表;
旋转的九九乘法表是第一行是1×1=1 1×2=2 1×3=3 1×4=4 ... 1×9=9; 第二行是2×2=4 2×3=6 2×4=8 ... 2×9=18; ... 第九行是9×9=81;
#!/bin/bash # for I in $(seq 1 9) ; do for J in $(seq 1 $I) ;do echo -ne "$I×$J=$[I*J]\t" done echo done for M in $(seq 1 9) ; do for N in $(seq $M 9) ; do echo -ne "$M×$N=$[N*M]\t" done echo done