Linux基础学习笔记6-SHELL编程
编程基础
程序:指令+数据
程序编程风格:
过程式:以指令为中心,数据服务于指令
对象式:以数据为中心,指令服务于数据
shell程序:提供了编程能力,解释执行
编程基本概念:
顺序执行;循环执行;选择执行
shell编程:过程式、解释执行
编程语言的基本结构
各种系统命令的组合
数据存储:变量、数组
表达式:a+b
语句:if
shell脚本基础
shell脚本:包含一些命令或声明,并符合一定格式的文本文件
格式要求:首行shebang机制
#! /bin/bash
#! /usr/bin/python
#! /usr/bin/perl
shell脚本的用途有:
自动化常用命令
执行系统管理和故障排序
创建简单的应用程序
处理文本或文件
创建shell脚本
第一步:使用文本编辑器来创建文本文件
第一行必须使用包括shell声明序列:#!
#!/bin/bash
添加注释
注释以#开头
第二步:运行脚本
给予执行权限,在命令行上指定脚本作为解释器程序的参数运行
直接运行解释器,将脚本作为解释器程序的参数运行 脚本规范:
脚本代码开头约定
1.第一行一般为调用使用的语言
2.程序名,避免更改文件名为无法找到正确的文件
3.版本号
4.更改后的时间
5.作者相关信息
6.该程序的作用,及注意事项
7.最后是各版本的更新及简要说明
脚本的基本结构:
#!SHEBANG
CONFIGURATION_VARIABLES
FUNCTION_DEFINITIONS
MAIN_CODE shell脚本示例:

脚本调试
检测脚本中语法错误
bash -n /path/to/some_script
调试执行
bash -x /path/to/some_script
变量
变量:命名的内存空间
数据存储方式:
字符:
数值:整型、浮点型
变量:变量类型
作用:1.数据存储格式
2.参与的运算
3.表示的数据范围 强类型:变量不经过强制转换,它永远是这个数据类型,不允许隐式的类型转换。一般定义变量时必须指定类型、参与运算必须符合类型要求;调用未声明变量会产生错误。如java,c#
弱类型:语言的运行时会隐式做数据类型转换。无须指定类型,默认均为字符型;参与运算会自动进行隐式类型转换;变量无须事先定义可直接调用。如bash不支持浮点数,php
变量命名规则:
1.不能使用程序中的保留字:例如if,for
2.只能使用数字、字母及下划线,且不能以数字开头
3.见名知义
4.统一命名规则:驼峰命名法
bash中变量的变种
根据变量的生效范围等标准划分下面变量类型:
局部变量:生效范围为当前shell进程;对当前shell之外的其他shell进程,包括当前shell的子shell进程均无效
环境(全局)变量:生效范围为当前shell进程及其子进程(利用export声明即为环境变量)
本地变量:生效范围为当前shell进程中某代码片段,通常指函数
位置变量:$1,$2,...来表示,用于让脚本在脚本代码中调用命令行传递给它的参数
特殊变量:$?,$0(代表脚本名称),$*(代表所有参数),$@(代表所有参数),$#(代表参数数量),$$
注意:#@与#*的区别在于#*会将所有位置参数当成一个整体
echo $$:查看当前shell运行的系统编号
pstree -p:查看当前系统运行的shell树状结构
scp命令:可以跨网络将本机数据发送到另外一台机器上 局部变量
变量赋值:name='value'
可以使用引用value:
(1)可以是直接字串;name="root"
(2)变量引用:name="$USER"
(3)命令引用:name='COMMAND' name=$(COMMAND)
变量引用:${name} $name
"":弱引用,其中的变量引用会被替换为变量值
'':强引用,其中的变量引用不会被替换为变量值,而保持源字符串
显示已定义的所有变量:set
删除变量:unset name 环境变量
变量声明、赋值
export name=VALUE
declare -x name=VALUE
变量引用:$name,${name}
显示所有环境变量:
env
printenv
export
declare -x
删除变量 unset name bash内建的环境变量:PATH,SHELL,USER,UID,HOME,PWD,SHLVL,MAIL,HISTSIZE,- 等等。

只读和位置变量
只读变量:只能声明,但不能修改和删除
声明只读变量:readonly name
declare -r name
查看只读变量:readonly -p
位置变量:在脚本代码中调用通过命令行传递给脚本的参数
$1,$2,...:对应第一,第二等参数,shift[n]换位置
$0:命令本身
$*:传递给脚本的所有参数。全部参数合为一个字符串
$@:传递给脚本的所有参数,每个参数为独立字符串
$#:传递给脚本的参数个数
$@ $* 只在被双引号包起来的时候才会有差异
set -- 清空所有位置变量
退出状态
进程使用退出状态来报告成功或失败
0代表成功,1-255代表失败
$?变量保存最近的命令退出状态
例如:
print -c1 -W1 hostdown &> /dev/null
echo $?
退出状态码
bash自定义退出状态码
exit[n]:自定义退出状态码
注意:脚本中一旦遇到exit命令,脚本会立即终止;终止退出状态取决于exit命令后面的数字;
如果未给脚本指定退出状态码,整个脚本的退出状态码取决于脚本中执行的最后一条命令的状态码
算术运算
bash中的算术运算:help let
+,-,*,/,%取模(取余),**(乘方)
实现算术运算:
(1)let var=算术表达式
(2)var=$[算术表达式]
(3)var=$((算术表达式))
(4)var=$(expr arg1 arg2 ...)
(5)declare -i var =数值
(6)echo '算术表达式' | bc
乘法符号在有些场景中需要转义,如*
bash有内建的随机数生成器:$RANDOM(0-32767)
echo $[$RANDOM%50]:0-49之间随机数 赋值:+=,-=,==,/=,%=
let var OPER value:let count+=3
自增自减:let var +=1 ;let var++ ;let var -=1; let var--;
逻辑运算

条件测试
判断某需求是否满足,需要由测试机制来实现
专用的测试表达式需要由测试命令辅助完成测试过程
评估布尔声明,以便用在条件性执行中
若真,则返回0
若假,则返回1
测试命令:
test EXPRESSION
[EXPRESSION]
[[EXPRESSION]](这种情况适用于带有正则表达式的情况)
注意:EXPRESSION前后必须有空白字符 条件性的执行操作符
根据退出状态而定,命令可以有条件地运行
&& 代表条件性的AND THEN
|| 代表条件性的OR ELSE
例如:
grep -q no_such_user /etc/passwd || echo 'No such user'
输出:No such user
ping -c1 -W2 station &> /dev/null > && echo "Station1 is up" > ||(echo 'Station1 is unreachable';exit1)
输出:Station1 is up test命令(内部命令,查看帮助:help test)
长格式的例子:
test "$A" == "$B" && echo "Strings are equal"
test "$A" -eq "$B" && echo "Integers are equal"
简写格式的例子:
["$A" == "$B"] && echo "Strings are equal"
["$A" -eq "$B"] && echo "Integers are equal"
bash的数值测试
-v VAR:变量VAR是否设置
数值测试:
-gt 是否大于
-ge 是否大于等于
-eq 是否等于
-ne 是否不等于
-lt 是否小于
-le 是否小于等于
bash的字符串测试
== 是否等于
> ascii码是否大于ascii码
< 是否小于
!= 是否不等于
=~ 左侧字符串是否能够被右侧的PATTERN所匹配(此表达式一般用于[[]]中;扩展的正则表达式)
-z "STRING" 字符串是否为空,空为真,不空为假
-n "STRING" 字符串是否不空,不空为真,空为假
注意:用于字符串比较时用到的操作数都应该使用引号
bash的文件测试
存在性测试
-a FILE:同-e
-e FILE:文件存在性测试,存在为真,否则为假
存在性及类别测试
-b FILE:是否存在且为设备文件
示例:[-f /etc/issue] && echo true
[-d /etc/] && echo true
bash文件权限测试
文件权限测试:
-r FILE:是否存在且可读
-w FILE:是否存在且可写
-x FILE:是否存在且可执行
文件特殊权限测试:
-u FILE:是否存在且拥有suid权限
-g FILE:是否存在且拥有sgid权限
-k FILE:是否存在且拥有sticky权限
bash的文件属性测试
文件大小测试
-s FILE:是否存在且非空
文件是否打开:
-t fd:fd文件描述是否在某终端已经打开
-N FILE:文件自从上一次被读取之后是否被修改过
-O FILE:当前有效用户是否为文件属主
-G FILE:当前有效用户是否为文件属组
双目测试:
FILE1 -ef FILE2:FILE1是否是FILE2的硬链接
FILE1 -nt FILE2:FILE1是否新于FILE2(mtime)
FILE1 -ot FILE2:FILE1是否旧于FILE2
bash的组合测试条件
第一种方式:
COMMAND1 && COMMAND2
COMMADN1 || COMMADN2
!COMMAND
如:[[ -r FILE ]] && [[ -w FILE ]]
第二种方式:
EXPRESSION1 -a EXPRESSION2
EXPRESSION1 -o EXPRESSION2
!EXPRESSION
必须使用测试命令进行
示例:[ -z "$HOSTNAME" -o "$HOSTNAME"=="localhost.localdomain"] && hostname www.ccsu.com [ -f /bin/cat -a -x /bin/cat] && cat /etc/fstab
使用read命令来接收输入
使用read来把输入值分配给一个或多个shell变量
-p 指定要显示的提示
-s 静默输入,一般用于密码
-n N 指定输入的字符串长度
-d '字符'输入结束符
-t N TIMEOUT为N秒
read 从标准输入中读取值,给每个单词分配一个变量,所有剩余单词都被分配给最后一个变量
read -p "Enter a filename:" FILE
流程控制
过程式编程语言:
顺序执行
选择执行
循环执行
条件选择if语句
if语句示例:
read -p"please onput your age:" age
[[ "$age" =~ [0-9]+$ ]] ||{echo your age is false;exit10;}
if [ "$age" -gt 0 -a "$age" -le 18];then
echo "you are young"
elif[ "$age" -gt 18-a "$age" -le 50];then
echo woek hard
elif ["$age" -gt 50 -a "$age" -le 80];then
echo "very ok"
else
echo "you do not come from earth"
fi
条件判断:case语句
case语句示例:
read -p"Do you agree?tes or no:"anwser
case $answer in
[Yy]|([Yy][Ee][Ss])
echo your answer is yes
;;
[Nn]|[Nn][Oo])
echo your answer is no
;;
*)
echo your answer is false
;;
esac
循环
循环执行
将某段代码重复运行多次
重复运行多少次
循环次数事先已知
循环次数事先未知
有进入条件和退出条件
for;while;until
for循环
for循环示例1
显示root下所有的txt格式文件:
for name in `ls /root/*.txt`;do echo "$name";done
for循环示例2
求1-100之间的奇数和
sum=0;for number in `seq 1 2 100`;do let sum+=number;done;echo "sum is $sum"
while循环
while循环示例1
求1-100之间的奇数和
sum=0;i=1;while ["$i" -le 100];do let sum+=i;let i+=2;echo "sum is $sum"
until循环
循环控制语句continue
循环控制语句break
for循环的特殊用法:
for循环的特殊用法示例:
求1-100之间的奇数和
for((sum=0,i=1;i<100;i+=2));do let sum+=i;done;echo "sum is $sum"
函数介绍
函数function是由若干条shell命令组成的语句块,实现代码重用和模块化编程
它与shell程序形式上是相似的,不同的是它不是一个单独的进程,不能独立运行,而是shell程序的一部分
函数和shell程序比较相似,区别在于:
shell程序在子shell中运行
而shell函数在当前shell中运行。因此在当前shell中,函数可以对shell中变量进行修改
定义函数
cat /etc/init.d/functions 查看系统自定义的函数
函数使用
函数返回值
函数返回值示例:
checkip(){
[[ "$1" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]] && echo "This is a IP" || {echo "This is not IP" ;return 10;}
}
注意:返回值返回给了调用者
交互式环境下定义和使用函数
在脚本中定义及使用函数
定义一个ip检查函数
checkip(){
[[ "$1" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]] && echo "This is a IP" || echo "This is not IP"
}
调用函数
checkip
删除函数
unset checkip
使用函数文件
创建函数文件
载入函数
检查载入函数
执行shell函数
删除shell函数
函数参数:
函数变量
局部变量示例
函数递归示例
函数递归示例
fork炸弹
数组
数组赋值
引用数组
数组数据处理
数组示例1
数组示例2
Linux基础学习笔记6-SHELL编程的更多相关文章
- Linux学习笔记(17) Shell编程之基础
1. 正则表达式 (1) 正则表达式用来在文件中匹配符合条件的字符串,正则是包含匹配.grep.awk.sed等命令可以支持正则表达式:通配符用来匹配符合条件的文件名,通配符是完全匹配.ls.find ...
- Linux学习笔记(18) Shell编程之流程控制
1. if语句 (1) 单分支if条件语句 格式为: # 注意条件判断式两端的空格if [ 条件判断式 ];then 程序员 fi 或者 if[ 条件判断式 ] then 程序 fi 例:判断分区使用 ...
- Linux基础学习笔记2-文件管理和重定向
本节内容 1)文件系统结构元素 2)创建和查看文件 3)复制.转移和删除文件 4)软和硬链接 5)三种I/O设备 6)把I/O重定向至文件 7)使用管道 文件系统和结构 文件系统 文件和目录被组织成一 ...
- linux基础学习笔记
我用的是centOS7.0版本的系统.linux的shell终端窗口类似于wind的command窗口 shell命令提示符格式:用户名@主机名:目录名 提示符 @前面的是已登录的用户名,@之后的为计 ...
- Linux基础学习笔记5-软件管理
包管理器 二进制应用程序的组成部分: 二进制文件.库文件.配置文件.帮助文件 程序包管理器: debian:deb文件.dpkg包管理器 redhat:rpm文件.rpm包管理器 rpm:Redhat ...
- Linux基础学习笔记4-文本处理
本章内容 抽取文本的工具 文件内容:less和cat 文件截取:head和tail 按列抽取:cut 按关键字抽取:grep 文件查看 文件查看命令:cat,tac,rev cat [OPTION] ...
- Linux基础学习笔记3-用户权限
本章内容 用户user 令牌token,identity Linux用户:Uername/UID 管理员:root,0 普通用户:1-65535 系统用户:1-499,1-999(Centos7) 对 ...
- Linux基础学习笔记1
MBR分区 主分区: 1-4,一块硬盘最多四个主分区,对主机必须有,主区可以格式化ntfs,存数据: 扩展分区:1-4,一块硬盘最多一个扩展分区,可以没有扩展分区,划分更小的单元,即逻辑分区: 逻辑分 ...
- linux基础(6)-shell编程
shell脚本 shell脚本程序:以文件形式存放批量的linux命令集合,该文件能够被shell释放执行.通常由一段linux命令.shell命令.控制语句以及注释语句构成. shell脚本特点: ...
随机推荐
- 动态记忆网络(DMN)
论文:Ask Me Anything: Dynamic Memory Networks for Natural Language Processing 1.概述 Question answering( ...
- 第一章 mysql的体系结构与存储引擎
数据库从逻辑上可以分为两部分,一部分负责存储即文件系统,这部分有个更时髦的名字叫存储引擎,存储引擎负责如何把数据以及索引相关的内容以合适的形式组织并存储到磁盘上.另一部分为server部分,负责和用户 ...
- PHP HMAC_SHA1 算法 生成算法签名
HMAC_SHA1(Hashed Message Authentication Code, Secure Hash Algorithm)是一种安全的基于加密hash函数和共享密钥的消息认证协议. 它可 ...
- tomcat 安装配置部署到nginx+tomcat+https
目录 1 Tomcat简介 2.下载并安装Tomcat服务 2.2 部署java环境 2.3 安装Tomcat 2.4 Tomcat目录介绍 (关注点 bin conf logs webapps) 2 ...
- Bean named '*' must be of type [*], but was actually of type []
本地Service 名字和调用别的maven项目Service重名
- windows系统VS2017编译boost
1. 下载boost, 解压,进入boost源目录 2. 打开vs2017 x86 CMD工具,输入bootstrap.bat,等待初始化完毕 x86编译 bjam stage --toolset=m ...
- 项目代码迁移(使用git)
克隆老仓库(裸仓库):git clone --bare git@codehub.devcloud.huaweicloud.com:e2f197xxxxxxx19fc4ae7348b2ed41/Node ...
- linux日志:syslogd和klogd及syslog
一. 日志守护进程 syslogd和klogd是很有意思的守护进程,syslogd是一个分发器,它将接收到的所有日志按照/etc/syslog.conf的配置策略发送到这些日志应该去的地方,当然也包括 ...
- JVM-Java内存区域
JVM虚拟机运行时数据区结构分为: 其中方法区和堆是所有线程共享的内存区域,而Java栈.本地方法栈.程序计数器是线程私有的. 我们详细介绍运行时数据区的各个区域及其作用. 程序计数器: 一块较小的内 ...
- NuGet的本地服务器安装与Package的发布(呕吐)
主要的步骤是按照下面的例子来做的: NuGet学习笔记(1)——初识NuGet及快速安装使用 NuGet学习笔记(2)——使用图形化界面打包自己的类库 NuGet学习笔记(3)——搭建属于自己的NuG ...