朗科学习期间心得笔记(九)
bash脚本编程的结构:
bash脚本编程语言:
脚本类语言
解释型语言
过程式编程语言
过程式编程语言的结构:
顺序执行结构:从上到下,从左向右的执行所有语句(命令);
选择执行结构:当条件满足或不满足时,才会执行对应的语句(命令);
循环执行结构:重复执行某段语句(命令);
bash脚本编程语言中,也具备上述结构;其默认为顺序执行结构;
选择执行结构:根据给定条件的逻辑判断结果,或根据某个可选取的取值范围,进而选择某个分支结构中的命令语句予以执行的方式;
if:
选择执行结构的标准,根据条件的逻辑判断结果选择执行的语句内容;
case:
选择执行结构的标准,根据符合某特定范围的取值标准选择执行的语句内容;
循环执行结构:对于特定语句内容,重复执行0次,1次或多次;
for:以遍历列表的方式进行循环;
while:根据给定条件的逻辑判断结果;逻辑判断结果为真才循环,否则停止循环;
until:根据给定条件的逻辑判断结果;逻辑判断结果为假才循环,否则停止循环;
select:死循环,即没有默认退出条件的循环;利用循环提供一个可选择的列表;例如: $RANDOM
bash脚本的执行结构---if选择执行结构
if 命令; then 命令; [ elif 命令; then 命令; ]... [ else 命令; ] fi
if语句的单分支结构
if 命令; then 命令; fi
注意:是否会执行then后的命令,取决于if后命令的状态返回值,如果其返回值为真则执行then后的命令,否则不执行then后的命令;
建议在脚本中的书写格式:
if CONDITION(条件) ;then
STATEMENT
...
fi
if语句的双分支结构
if 命令; then 命令; [ else 命令; ] fi
注意:如果其返回值为真则执行then后的命令,返回值为假则执行else后的命令;
if CONDITION(条件) ;then
STATEMENT
...
else
...
fi
if语句的多分支结构
if 命令; then 命令; [ elif 命令; then 命令; ]... [ else 命令; ] fi
注意:是否会执行then后的命令,取决于if后命令的状态返回值或elif后命令的状态返回值,如果if为真则执行then后命令,如果为假则继续判断第一个elif后命令的返回值,第一个elif返回值为真则执行第一个elif语句中then后命令,否则判断第二个elif后命令的返回值.....如果所有的if,elif后的命令返回值都为假,则执行else后ude命令;
if CONDITION(条件) ;then
STATEMENT
...
elif CONDITION2 ; then
STATEMENT
...
elif CONDITION2 ; then
STATEMENT
...
...
else
...
fi
注意:if的多分支结构,使用场景不多,而且有些时候,可以使用嵌套的单分支或双分支if结构代替多分支结构;
嵌套if结构:
if condition1 ; then
if condition2 ; then
if condition3 ; then
statement
...
else
statement
...
fi
else
statement
...
fi
else
statement
...
fi
示例:
1.写一个脚本,判断某个用户的默认登录shell是否为/bin/bash;
#!/bin/bash
#
USERNAME=$(cut -d: -f1 /etc/shadow | sort -R | head -1)
USERSHELL=$(egrep "^$USERNAME\>" /etc/passwd | cut -d: -f7)
if [ "$USERSHELL" == "/bin/bash" ] ; then
echo "${USERNAME}'s login shell is /bin/bash."
fi
unset USERNAME USERSHELL
2.写一个脚本,判断某个用户的默认登录shell是否为/bin/bash,如果不是,显示其登录shell
#!/bin/bash
#
USERNAME=$(cut -d: -f1 /etc/shadow | sort -R | head -1)
USERSHELL=$(egrep "^$USERNAME\>" /etc/passwd | cut -d: -f7)
if [ "$USERSHELL" == "/bin/bash" ] ; then
echo "${USERNAME}'s login shell is /bin/bash."
else
echo "${USERNAME}'s login shell is ${USERSHELL}"
fi
unset USERNAME USERSHELL
bash脚本编程---用户交互使用
位置参数变量:
$0:命令的本身,对于脚本而言,就是该脚本的路径;
$1,$2,...$n:脚本后面通过命令行给脚本传递的命令行参数;
n>9时,引用该位置变量时需要加 {} 即:${10}
特殊变量:
$@:给出的所有位置参数的列表,当使用双引号引用时,每个参数作为单独字符串存在;
$*:给出的所有位置参数的列表,当使用双引号引用时,整个参数列表被当作字符串;
$#:表示除去$0之外,整个命令行中有多少个参数;即 参数的个数;
read命令:
Read a line from the standard input and split it into fields.
read - read [-a array] [-p prompt] [-t timeout] [name ...]
-a array:定义索引数组;
-p prompt:给用户输出提示信息;
-t timeout:用户输入的超时时间;
name:变量或数组的名称;如果省略此内容,bash会将read读到的信息直接保存到内置的名为REPLY变量中;
注意:
linux哲学思想之一:尽量不与用户交互;
在使用read命令时,通常会使用-t选项来指定与用户交互的时间,一旦时间超过预定时间,脚本中后续的命令内容会自动被执行;因此,通常需要在后面判断通过read赋值的变量值是否为空,如果为空,可能需要为该变量提供默认值;
read -t 5 VAR1
[ -z $VAR1 ] && VAR1=value1
管理用户脚本:
脚本可以接受两个参数,第一个参数为-a或-d,第二个参数为用户名;如果第一个参数是-a,则创建其后面参数命名的用户;如果第一个参数为-d,则删除其后面参数命名的用户;
#!/bin/bash
#
if [ $# -ne 2 ] ; then
echo "Make sure provide TWO arguments."
exit 5
fi
if [ $1 == '-a' ] ; then
if ! id $2 &> /dev/null ; then
useradd $2 &> /dev/null
echo $2 | passwd --stdin $2 &> /dev/null
echo "User $2 created succesfully and password changed to it's username."
else
echo "$2 exists already."
fi
elif [ $1 == '-d' ] ; then
if id $2 &> /dev/null ; then
userdel -r $2 &> /dev/null
echo "User $2 delete finished."
else
echo "$2 does not exist yet."
fi
else
echo "Usage: $(basename $0) -a USERNAME | -d USERNAME"
exit 6
fi
改进版:使用read命令;
#!/bin/bash
#
if [ $# -ne 1 ] ; then
echo "Make sure provide ONE argument."
exit 5
fi
if [ $1 == '-a' ] ; then
read -p "Please input a username for creating: " USERNAME
if ! id $USERNAME &> /dev/null ; then
useradd $USERNAME &> /dev/null
echo $USERNAME | passwd --stdin $USERNAME &> /dev/null
echo "User $USERNAME created succesfully and password changed to it's username."
else
echo "$USERNAME exists already."
fi
elif [ $1 == '-d' ] ; then
read -p "Please input a username for deleting: " USERNAME
read -t 5 -p "confirm? Input 'yes' to continue: " CHOICE
[ -z $CHOICE ] && CHOICE='no'
if [ $CHOICE == 'yes' ] ; then
if id $USERNAME &> /dev/null ; then
userdel -r $USERNAME &> /dev/null
echo "User $USERNAME delete finished."
else
echo "$USERNAME does not exist yet."
fi
else
echo
echo "$USERNAME is not deleted."
fi
else
echo "Usage: $(basename $0) { -a | -d }"
exit 6
fi
写脚本解决问题:
1.判断用户通过命令行给的一个参数是否为整数。
#!/bin/bash
#
if [ $# -ne 1 ] ; then
echo "Make sure provide ONE digit."
exit 5
fi
# if ! [[ $1 =~ [^[:digit:]] ]] ; then
if [[ $1 =~ ^[[:digit:]]+$ ]] ; then
echo "$1 is a pure digit."
else
echo "$1 is not a digit."
fi
循环执行结构:
循环:将某一段代码或命令重复执行0次,1次或多次;
一个好的循环结构,必须要包括两个重要的环节:
1.进入循环的条件:
在符合要求或满足条件时才开始循环;
2.退出循环的条件
达到某个要求或符号某个条件时需要结束或终止循环的执行;
for循环:
1.遍历列表的循环:
Execute commands for each member in a list.
for - for NAME [in WORDS ... ] ; do COMMANDS; done
建议在脚本中的书写格式:
for VAR_NAME in LIST ; do
循环体
done
或
for VAR_NAME in LIST
do
循环体
done
注意:
VAR_NAME:任意指定的变量名称,变量的值是从LIST中遍历获取的各个元素;
LIST:for循环需要遍历的列表;可以通过以下方式生成列表:
1.直接给出列表;
2.纯整数列表:
1) 花括号展开:
{FIRSTNUMM..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
grep /PATH/TO/SOMEFILE
5.GLOBBING
6.某些特殊变量的值:
$*, $@
循环体:
一般来说,循环体中应该包括能够用到VAR_NAME变量的值的命令或命令的组合;如果循环体中的命令并没有用到VAR_NAME变量的值的话,列表的元素个数就是此次for循环的次数;
写一个脚本,计算1到100的数字之和;
#!/bin/bash
#
declare -i SUM=0
for I in {1..100} ; do
SUM=$[SUM+I]
done
echo "The summary is: $SUM"
写一个脚本,能够通过-a或-d选项添加或删除一个或多个用户账户;
#!/bin/bash
#
if [ $# -lt 2 ] ; then
echo "Make sure provide more than TWO arguments."
exit 5
fi
if [ $1 == '-a' ] ; then
shift
for I in "$@" ; do
if ! id $I &> /dev/null ; then
useradd $I &> /dev/null
echo $I | passwd --stdin $I &> /dev/null
echo "User $I created succesfully and password changed to it's username."
else
echo "$I exists already."
fi
done
elif [ $1 == '-d' ] ; then
shift
for J in "$@" ; do
if id $J &> /dev/null ; then
userdel -r $J &> /dev/null
echo "User $J delete finished."
else
echo "$J does not exist yet."
fi
done
else
echo "Usage: $(basename $0) -a UNAME1 [UNAME2 ...] | -d UNAME1 [UNAME2 ...]"
exit 6
fi
总结:
1.进入循环的条件:LIST中尚有未被取尽的元素;
2.退出循环的条件:LSIT中的元素被取尽;
3.for循环几乎不会出现死循环;
4.在执行循环的过程中,需要将整个LIST载入内存,因此,对于大列表来说,可能会消耗较多的内存及CPU资源;
计算指定数字范围内自然数的和:
#!/bin/bash
#
declare -i SUM=0
read -p "Please input TWO integer: " INT1 INT2
if [[ $INT1 =~ [^[:digit:]] ]] ; then
echo "$INT1 must be an integer."
exit 5
fi
if [[ $INT2 =~ [^[:digit:]] ]] ; then
echo "$INT2 must be an integer."
exit 5
fi
if [ $INT1 -gt $INT2 ] ; then
for I in $(seq $INT2 $INT1) ; do
# SUM=$[SUM+I]
let SUM+=$I
done
echo "The summary is: $SUM"
else
for I in $(seq $INT1 $INT2) ; do
# SUM=$[SUM+I]
let SUM+=$I
done
echo "The summary is: $SUM"
fi
写一个脚本,打印有"*"组成的倒置的等腰三角形;
********* 1行,0个空白字符,9个*
******* 2行,1个空白字符,7个*
***** 3行,2个空白字符,5个*
*** 4行,3个空白字符,3个*
* 5行,4个空白字符,1个*
N行,N-1个空白字符,2*(总行数-当前行号)+1 个*
#!/bin/bash
#
if [ $# -ne 1 ] ; then
echo "Usage: $(basename $0) INTEGER"
exit 5
fi
if [[ $1 =~ [^[:digit:]] ]] ; then
echo "Usage: $(basename $0) INTEGER"
exit 6
fi
LINENUM=$1
for I in $(seq $LINENUM) ; do
for J in $(seq $[I-1]) ; do
echo -n " "
done
for K in $(seq $[2*(LINENUM-I)+1]) ; do
echo -n "*"
done
echo
done
打印九九乘法表
第一行:1个
第二行:2个
...
第九行:9个
#!/bin/bash
#
for I in {1..9} ; do
for J in $(seq $I) ; do
echo -ne "$I×$J=$[I*J]\t"
done
echo
done
#!/bin/bash
#
for (( I=1 ; I<=9 ; I++ )) ; do
for (( J=1 ; J<=I ; J++ )) ; do
echo -ne "$J×$I=$[I*J]\t"
done
echo
done
以上两个例子,均使用for循环的嵌套;往往需要两层的循环嵌套才能打印出平面效果;外层的for循环,负责控制行数输出;内层的for循环,负责控制每一行中各个列的输出;
2.通过控制变量实现for循环:
for (( exp1; exp2; exp3 )); do COMMANDS; done
可以在脚本中写成如下格式:
for (( exp1; exp2; exp3 )); do
COMMANDS
done
exp1:表达式1,为指定的变量赋初始值;
exp2:表达式2,此次循环的退出条件;
exp3:表达式3,指定的变量的值的变化规律;
计算从1到100的自然数的和;
#!/bin/bash
#
for (( I=1 ; I<=100 ; I++ )) ; do
let SUM+=$I
done
echo "The summary is: $SUM"
编程思想:
将人类的自然语言转换成程序的代码语言的方式;
转载于:https://blog.51cto.com/holmes975/2047234
朗科学习期间心得笔记(九)相关推荐
- 朗科学习期间心得笔记(一)
(一) 1.完整的操作系统由内核(kernel)和应用(application)组成. linux内核版本由 主版本号+次版本号+小改动 (注:在2.X的版本奇数代表测试版偶数代表稳定版) 可在 ht ...
- 朗科学习期间心得笔记(三)
vi编辑器:全屏文本编辑器 vi:visual interface,可视化界面: S.U.N:bill joy, vim相对于vi有更多的新特性: 1.语法着色显示: 2.更多的命令: 3.历史纪录: ...
- 朗科学习期间心得笔记(二)
基本命令: 7.touch:修改文件的时间戳. change file timestamps(如果文件不存在就会创建该文件) 常用选项: -c,--no-create;不创建任何文件 -a;仅修改文件 ...
- 朗科实习期间心得笔记(四)
SHELL: 用户与操作系统之间完成交互式操作的一个接口程序,为用户提供简化了的操作. 上世纪70年代中期,Bell实验室,由bourne开发,bourne shell,简称sh: Bill ...
- 朗科实习期间心得笔记(七)
bash多命令执行方法: 1.命令替换 COMMAND1 $(COMMAND2) 2.管道 COMMAND1 | COMMAND2 | COMMAND3 .... ...
- 朗科实习期间心得笔记(八)
其他的文本处理命令: wc命令 cut命令 在文件的每一行中提取片断 注意:能够被cut命令修剪的文本文件或数据内容,一般是具有某种特定格式或结构的文本文件或数据内容:如: ...
- 朗科实习期间心得笔记(六)
与用户账户和组账户相关的文件: /etc/passwd /etc/group /etc/shadow /etc/gshadow /etc/default/useradd /etc/login.defs ...
- 朗科实习期间心得笔记(五)
bash特性 十二.bash变量 变量:一段有名称的连续的内存空间:这段内存空间的名称,称为变量名,在这段内存空间中存储数据,则称为变量值: 向内存空间(变量)中存储数据的过程,称为赋值操作:赋值的符 ...
- JAVA基础学习精简心得笔记整理
JAVA基础学习精简心得笔记整理 配置java环境变量 Java的运行过程 基本数据类型 引用数据类型 逻辑运算符 数组 方法重载 封装 继承 多态 多态的作用 单例设计模式 接口interface ...
最新文章
- Linux--VI命令大全
- win8.1注册表-修改资源管理器的默认路径regedit
- 数学--数论--HDU - 6322 打表找规律
- python读取excel列数据库_python中读取excel数据库
- i5 1135g7什么水平_i7-10510U和i5-1135G7对比,该怎么选择呢?
- 【华为云技术分享】GitHub联合开发
- MySQL 5.7.18忘记密码和密码过期解决
- 麒麟系统安装lnmp
- 大数据比赛笔记(一)基本环境配置
- java structs教程_Java教程 实战学习Struts实例
- MacBook上不显示外接硬盘未装载解决方法
- macOS 安装 aria2 下载 BitTorrent 替代迅雷
- 【设计模式11】备忘录和解释器模式 SpelExpressionParser
- 卫星位置计算小程序(C#版)
- 51单片机实战教程(22 看门狗)
- 实验一Linux开发环境搭建与LED点亮
- 使用阿里云服务器的经历~
- 《笨办法学python》加分习题31——我的答案
- 做自媒体,有哪些免费下载视频剪辑素材的网站?
- 向用户发送短信验证码
热门文章
- i5 11300h核显相当于什么显卡
- android微信分享调不起微信,关于分享调不起微信客户端的解决办法
- android9的手机,手机 篇九:一加9R之光藏于机身内外 新品深度体验
- 安卓手机丢了而且被关机了_详细攻略:如何找回丢失或被盗的安卓手机
- 在两个TIA博途项目中组态PROFIBUS和PROFINET通信的具体方法
- python openpyxl合并单元格_python使用openpyxl excel 合并拆分单元格
- 关于微信公众号的h5页面跳转微信小程序的详细介绍
- csgo准星设置代码_【老许教你玩CSGO】如何调整合适的准星参数
- php查询返回对像,php – 如何从DQL查询返回对象?
- Cocos如何实现流畅的炮弹抛射?从公式推导开始,详解抛射体运动的实践与应用...