linux之基础shell脚本编程1 基础变量赋值

本章主要介绍函数的基础,变量赋值,逻辑运算,条件表达式,测试


 

一,编程基础的介绍


1.1 编程基础


程序是由指令和数据组成的

程序编程风格可分为面向对象和面向过程编程

   面向过程:以指令为中心,数据服务于指令

   面向对象:以数据为中心,指令服务于数据


sehll程序提供了编程能力,是通过解释器解释执行的


1.2 程序的执行方式


计算机只能运行二进制指令;

编程语言:

 低级:汇编

 高级:

   编译:高级语言 --> 编译器 --> 目标代码  比如 java,C# 等

   解释:高级语言 --> 解释器 --> 机器代码  比如 shell perl python 等


1.3 编程基本概念


编程逻辑处理方式:

  顺序执行

  循环执行

  选择执行

shell编程:过程式,解释执行

  编程语言的基本结构:

    数据存储:变量,数组 等

    表达式:a+b 等

    语句:if while 等


二,shell脚本编程


2.1 shell脚本基础


shell脚本是包含一些命令或声明,并符合一定格式的文本文件

格式要求:首行shebang机制

  #!/bin/bash

  #!/usr/bin/python

  #!/usr/bin/perl

shell脚本的用途:

自动化常用命令

执行系统管理和故障排除

创建简单的应用程序

处理文本或文件


2.2 创建shell脚本


第一步:使用文本编辑器来创建一个以 .sh 为结尾的文本文件,第一行必须包括shell声明序列:#!/bin/bash ;添加适当的注释,注释以 # 开头

第二步:运行脚本,首先,先给脚本赋予执行权限,在命令行上指定脚本的绝对或相对路径;也可以直接运行解释器,将脚本作为解释器程序的参数运行


脚本范例如下:


#!/bin/bash
#author: nineven
#Version: 1.0
#Description:This script displays some information about your
# environment 

echo "Greetings. The date and time are $(date)" echo "Your working directory is: $(pwd)"


2.3 脚本调试


 bash -n /path/to/some_script  :检查脚本中的语法错误(这个功能好像不怎么好用)

 bash -x /path/to/some_script  :调试执行,感觉很强大


2.4 编程程序语言分类


强类型:定义变量时必须指定类型,参与运算必须符合类型要求,调用未声明变量会产生错误,比如 java python

弱类型:无须指定类型,默认均为字符型,参与运算会自动进行隐式类型转换,变量无须事先定义可直接调用,比如 bash 不支持浮点数

变量命令法则:

 不能使用程序中的保留字:比如 if for 等

 只能使用数字,字母及下划线,且不能以数字开头

 见名知义


2.5 变量


变量:命名空间的内存空间

变量的数据存储方式:

 字符

 数值,比如 整形,浮点型

变量的类型:

 字符

 数值:整形,浮点型

变量的作用:

 数据存储格式

 参与的运算

 表示的数据范围


2.5.2 bash中的变量的种类


根据变量的生效范围等标准可分为以下几类:

 本地变量:生效范围为当前shell进程,对当前shell之外的其他shell进程,包括当前shell的子shell进程均无效

 环境变量:生效范围为当前shell进程及其子进程

 局部变量:生效范围为当前shell进程中某代码片段(通常指函数)

 位置变量:$1,$2,...来表示,用于让脚本在脚本代码中调用通过命令行传递给它的参数

 特殊变量:$?,$0,$*,$@,$#


2.5.2.1 本地变量


变量赋值: name='value'

可以使用引用value:

 可以直接是字符串:name="nineven"

 变量引用:name="$USER"

 命令引用:name=`command`,name=$(command)


变量引用:${name},$name

 "":弱引用,其中的变量引用会被替换为变量值

 '':强引用,其中的变量引用不会被替换为变量值,而是保持原字符串

显示已定义的所有变量:set

删除变量: unset name (删除变量时千万不要加 $ 符号)






实战训练1


1、编写脚本/root/bin/systeminfo.sh,显示当前主机系统信 息,包括主机名,IPv4地址,操作系统版本,内核版本, CPU型号,内存大小,硬盘大小。 

#!/bin/bash
echo -e  "The computer's info is"
name=$(hostname)
ip=$(ifconfig | sed -rn "s@^[[:space:]]+inet[[:space:]]+(.*)net.*@\1@p"|head -1)
sysinfo=$(cat /etc/centos-release)
kernav=$(uname -r)
cpuinfo=$(lscpu | sed -r -n 's@Model name.*:[[:space:]]+(.*)@\1@p')
meminfo=$( cat /proc/meminfo | head -1)
hhdinfo=$(fdisk -l | head -2|tail -1)
echo -e "\033[31m------主机名----------\033[0m"
echo $name
echo -e "\033[31m--------IPv4地址-----------------\033[0m"
echo -e $ip
echo -e "\033[31m---------操作系统版本-------------\033[0m"
echo $sysinfo
echo -e "\033[31m--------内核版本-----------------\033[0m"
echo $kernav
echo -e "\033[31m-------CPU型号------------------\033[0m"
echo $cpuinfo
echo -e "\033[31m----------内存大小---------------\033[0m"
echo $meminfo
echo -e "\033[31m-----硬盘大小--------------------\033[0m"
echo $hhdinfo
echo -e "\033[31m-------------------------\033[0m"

blob.png

2、编写脚本/root/bin/backup.sh,可实现每日将/etc/目录 备份到/root/etcYYYY-mm-dd中 

#!/bin/bash
cp -a /etc /root/etc`date +%F`

3、编写脚本/root/bin/disk.sh,显示当前硬盘分区中空间利 用率最大的值 

#!/bin/bash
echo "当前硬盘分区利用率最大值是 : `df  | egrep '\/dev\/sda*' | tr -s ' '|cut -d' ' -f5|sort -n|tail -1`"

blob.png

4、编写脚本/root/bin/links.sh,显示正连接本主机的每个远 程主机的IPv4地址和连接数,并按连接数从大到小排序

#!/bin/bash
echo "the links number is:"
netstat -nt |tr -s ' '  |cut -d ' ' -f5 |cut -d: -f1 |grep [0-9]|sort |uniq -c|sort -nr

blob.png




2.5.2.2 环境变量


变量声明,赋值:

 export name=VALUE

 declare -x name=VALUE

变量引用:$name,${name}

显示所有环境变量:

 export

 env

 printenv

删除:unset name

bash有许多内建的环境变量:PATH,SHELL,USER,UID,HISTSIZE,HOME,PWD,OLDPWD,HISTFILE,PS1等


2.5.2.3 只读和位置变量


只读变量:只能声明,但不能修改和删除

 readonly name

 declear -r name

位置变量:在脚本代码中调用通过命令行传递给脚本的参数

 $1,$2,...:对应第1,第2等参数,shift [n] 换位置

 $0:命令本身

 $*:传递给脚本的所有参数,全部参数合为一个字符串

 $@:传递给脚本的所有参数,每个参数为独立字符串

 $#:传递给脚本的参数的个数

$@ $* 只在被双引号包起来的时候才会有差异

比如:判断给出的文件的行数

#!/bin/bash
linecount="$(wc -l $1| cut -d' ' -f1)"
echo "$1 has $linecount lines."

blob.png


三,shell脚本运算


3.1 算术运算


bash中的算术运算可以通过 help let 命令查看

 + - * / %取模(取余) **(乘方)

实现算术运算:

 let var=算术表达式

 var=$[算术表达式]

 var=$((算术表达式))

 var=$(expr arg1 arg2 arg3 ...)

 declare -i var = 数值

 echo `算术表达式`|bc

乘法符号有些场景中需要转义,如*

bash中有内建的随机数生成器:$RANDOM 可以生成 1-32767 ,比如

echo $[$RANDOM%80] :表示0-79之间的随机数
[root@centos7 ~]# echo $[$RANDOM%81]
73
[root@centos7 ~]# echo $[$RANDOM%81]
9
[root@centos7 ~]# echo $[$RANDOM%81]
80


3.2 赋值


增强型赋值:

 += ,-= ,*= ,/= ,%=

let varOPERvalue

 例如: let count+=3  自加3后的值重新赋给自己

自增,自减:

 let var+=1

 let var++

 let var-=1

 let var--






实战训练2


1:写一个脚本/root/bin/sumid.sh,计算/etc/passwd 文件中的第10个用户和第20用户的ID之和

#!/bin/bash
echo "ID sum is : `sed -n '10p;20p' /etc/passwd | cut -d: -f3 | paste -s -d '+'| bc`"

blob.png

2:写一个脚本/root/bin/sumspace.sh,传递两个文件 路径作为参数给脚本,计算这两个文件中所有空白行之和 

#!/bin/bash
echo "文件空白行总共有: `cat $1 $2 | grep -c '^[[:space:]]*$'` 行"

blob.png

3:写一个脚本/root/bin/sumfile.sh,统计/etc, /var, /usr目录中共有多少个一级子目录和文件

#!/bin/bash
echo $[$(ls -a /etc /var /usr |wc -l)-6]

 我感觉 . .. 应该不是子目录吧,所以我在得到的结果减去6



3.3 逻辑运算


true ,false

1    0

与:

 同一为一,其余为零

 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,第二个必须要参与运算

异或:^

 异或的两个值,相同为假,不同为真


3.4 聚集命令




有两种聚集命令的方法:

 复合式:date;who |wc -l   命令会一个接一个地运行

 子shell:(date;who |wc -l) >> /tmp/trace  所有的输出都被发送给单个STDOUT和STDERR 


3.5 退出状态及退出码


进程使用退出状态来报告成功或失败

 0 代表成功,1-255代表失败

 $? 变量保存最近的命令退出状态

例如

 

[root@centos7 testdir]# ping -c1 -W1 10.1.0.1  &> /dev/null
[root@centos7 testdir]# echo $?
0
[root@centos7 testdir]# ping -c1 -W1 10.1.2.1  &> /dev/null
[root@centos7 testdir]# echo $?
1

成功返回0 失败返回非0


bash自定义退出状态码 

 exit [n] :自定义退出状态码

注意:脚本中一旦遇到exit命令,脚本会立即终止,终止退出状态取决于exit命令后面的数字

    如果未给脚本指定退出状态码,整个脚本的退出状态码取决于脚本中执行的最后一条命令的状态码



四,测试


4.1 条件测试


判断某需求是否满足,需要由测试机制来实现

专用的测试表达式需要由测试命令辅助完成测试过程

评估布尔声明,以便用在条件性执行中

 若真,则返回0

 若假,则返回1

测试命令

 test EXPRESSION

 [ EXPRESSION ]

 [[ EXPRESSION ]]

 注意:EXPRESSION前后必须有空白字符


4.2 条件性的执行操作符


根据退出状态而定,命令可以有条件地运行

 && 代表条件性的AND THEN

 || 代表条件性的OR ELSE

比如:

[root@centos7 testdir]# grep -q root /etc/passwd && echo 'user is exist' || echo 'no user'
user is exist
[root@centos7 testdir]# grep -q roota /etc/passwd && echo 'user is exist' || echo 'no user'
no user


[root@centos7 testdir]# ip="10.1.0.122"
[root@centos7 testdir]# ping -c1 -W1 $ip &> /dev/null && echo 'ip is up' || echo 'ip is down'
ip is down
[root@centos7 testdir]# ip="10.1.0.1"
[root@centos7 testdir]# ping -c1 -W1 $ip &> /dev/null && echo 'ip is up' || echo 'ip is down'
ip is up


4.3 test命令


长格式的例子如下:

[cent@centos7 ~]$ A=abcd
[cent@centos7 ~]$ B=abcd
[cent@centos7 ~]$ test $A == $B && echo 'strings are equal' || echo 'strings are not equal'
strings are equal
[cent@centos7 ~]$ B=abcde
[cent@centos7 ~]$ test $A == $B && echo 'strings are equal' || echo 'strings are not equal'
strings are not equal
[cent@centos7 ~]$ test $A -eq $B && echo 'strings are equal' || echo 'strings are not equal'
-bash: test: abcd: integer expression expected  #字符串不能做 -eq 运算
strings are not equal
[cent@centos7 ~]$ A=18
[cent@centos7 ~]$ B=18
[cent@centos7 ~]$ test $A -eq $B && echo 'Integers are equal' || echo 'Integers are not equal'
Integers are equal
[cent@centos7 ~]$ B=19
[cent@centos7 ~]$ test $A -eq $B && echo 'Integers are equal' || echo 'Integers are not equal'
Integers are not equal


简写格式的例子如下:

[cent@centos7 ~]$ [$A -eq $B] && 'Integers are equal' || echo 'Integers are not equal'
bash: [18: command not found...     # [ EXPRESSION ] ,EXPRESSION表达式前后必须有空白字符
[cent@centos7 ~]$ [ $A -eq $B ] && 'Integers are equal' || echo 'Integers are not equal'
Integers are not equal
[cent@centos7 ~]$ B=18
[cent@centos7 ~]$ [ $A -eq $B ] && echo 'Integers are equal' || echo 'Integers are not equal'
Integers are equal
[cent@centos7 ~]$ A=abcd
[cent@centos7 ~]$ B=abcd
[cent@centos7 ~]$ [ $A == $B ] && echo 'strings are equal' || echo 'strings are not equal'
strings are equal


4.4 bash的测试类型


4.4.1 数值测试


 -gt :是否大于

 -ge :是否大于等于

 -eq :是否等于

 -ne :是否不等于

 -lt :是否小于

 -le :是否小于等于


[cent@centos7 ~]$ A=1;B=4
[cent@centos7 ~]$ [ $A -gt $B ] && echo '成立' || echo '不成立'
不成立    
[cent@centos7 ~]$ [ $A -ge $B ] && echo '成立' || echo '不成立'
不成立
[cent@centos7 ~]$ [ $A -lt $B ] && echo '成立' || echo '不成立'
成立
[cent@centos7 ~]$ [ $A -ne $B ] && echo '成立' || echo '不成立'
成立
[cent@centos7 ~]$ [ $A -eq $B ] && echo '成立' || echo '不成立'
不成立
[cent@centos7 ~]$ [ $A -le $B ] && echo '成立' || echo '不成立'
成立


4.4.2 字符串测试


 == :是否等于

 > :左面的ascii 码是否大于右面字符串的ascii码

 < :左面的ascii 码是否小于右面字符串的ascii码

 != :是否不等于

 =~ :左侧字符串是否能够被右侧的PATTERN所匹配;注意:此表达式一般用于 [[ ]] 中

 -z "STRING" :字符串是否为空,空为真,不空为假

 -n "STRING" :字符串是否非空,非空为真,空为假

注意:用于字符串比较时的用到的操作数都应该使用引号


参数功能
数值测试
 -gt是否大于
 -ge是否大于等于
 -eq是否等于
 -ne是否不等于
 -lt是否小于
 -le是否小于等于
字符串测试
 ==是否等于
 > ascii码是否大于ascii码 
 <是否小于
 !=是否不等于
 =~ 左侧字符串是否能够被右侧的PATTERN所匹配 注意: 此表达式一般用于[[]] 中 
 -z "string"字符串是否为空,空为真,不空为假 
 -n "string"字符串是否不空,不空为真,空为假 
注意:用于字符串比较时的用到的操作数都应该使用引号



实战训练3


1、写一个脚本/root/bin/argsnum.sh,接受一个文件路径作 为参数;如果参数个数小于1,则提示用户“至少应该给一个 参数”,并立即退出;如果参数个数不小于1,则显示第一个 参数所指向的文件中的空白行数 

#!/bin/bash
[ $# -ge 1 ] && echo "文件空白行数为: `grep -c '^[[:space:]]*$' $1`" || echo '至少应该给一个参数'


[cent@centos7 scripts]$ bash argsnum.sh /etc/passwd
文件空白行数为: 0
[cent@centos7 scripts]$ bash argsnum.sh /testdir/aa
文件空白行数为: 42
[cent@centos7 scripts]$ bash argsnum.sh 
至少应该给一个参数

2、写一个脚本/root/bin/hostping.sh,接受一个主机的 IPv4地址做为参数,测试是否可连通。如果能ping通,则提 示用户“该IP地址可访问”;如果不可ping通,则提示用户“ 该IP地址不可访问”

#!/bin/bash
ping -c1 -W1 $1 &> /dev/null && echo "该ip可以访问" || echo "该ip地址不可访问"


[cent@centos7 scripts]$ bash hostping.sh 10.1.0.1
该ip可以访问
[cent@centos7 scripts]$ bash hostping.sh 10.1.0.3
该ip地址不可访问




4.4.3 文件测试


参数功能
文件存在性测试
 -e FILE文件存在性测试,存在为真,否则为假
 -a FILE文件存在性测试,存在为真,否则为假
存在性及类别测试
 -b FILE是否存在且为块设备文件
 -c FILE是否存在且为字符文件
 -d FILE是否存在且为目录文件
 -f FILE 或 -L FILE是否存在且为普通文件
 -h FILE是否存在且为符号链接文件
 -p FILE是否存在且为管道文件
 -S FILE是否存在且为套接字文件
文件权限测试
 -r FILE是否存在且可读
 -w FILE是否存在且可写
 -x FILE是否存在且可执行
文件特殊权限测试
 -g FILE是否存在且拥有sgid权限
 -u FILE是否存在且拥有suid权限
 -k FILE是否存在且拥有sticky权限
文件大小测试
 -s FILE是否存在且非空
文件是否打开
 -t fdfd表示文件描述符是否存在已经打开且与某终端相关
 -N FILE文件自动上一次被读取之后是否被修改过
 -O FILE当前有效用户是否为文件属主
 -G FILE当前有效用户是否为文件属组
双目测试
FILE1 -ef FILE2FILE1与FILE2是否指向同一个设备上的相同的inode
FILE1 -nt FILE2FILE1是否新于FILE2
FILE1 -ot FILE2

FILE1是否旧于FILE2



  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值