shell脚本编程基础(1)

要想玩转Linux系统,编写shell脚本是必须要掌握的技能。那什么是shell编程呢?简单来说,shell编程就是对多个Linux命令进行逻辑处理。

下面,我们从编程的基础开始讲起:

一、编程基础

1.什么是程序?

程序是指:指令+数据

程序编程风格可分为:

​ 过程式:以指令为中心,数据服务于指令(关注过程,小软件开发)

​ 对象式:以数据为中心,指令服务于数据(关注结果,适合开发大型软件)

2.程序的执行方式

计算机:运行二进制命令

编程语言:

低级:汇编

高级:

编译:高级语言–>编译器–>目标代码 (由程序员完成编译器翻译过程,安全性相对好)

java,C#

解释:高级语言–>解释器–>机器代码 (由电脑完成解释器翻译过程,安全性不如编译型)

shell,perl,python

shell程序:提供了编程能力,解释执行

3.编程基本概念

编程逻辑处理方式:

​ 顺序执行

​ 循环执行

​ 选择执行

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

编程语言的基本结构:

各种系统命令的组合

数据存储:变量、数组

表达式:a+b

语句:if

二、脚本基本格式

格式要求:

首行shebang机制(即声明脚本使用哪种编程语言)

如: #!/bin/bash

#!/bin/python

shell脚本的用途有:

自动化常用命令

执行系统管理和故障排除

创建简单的应用程序

处理文本或文件

运行脚本:

  1. 给予执行权限,执行
  2. 直接运行解释器,将脚本作为解释器程序的参数运行

脚本规范:

脚本代码开头约定:

  1. 第一行一般为调用使用的语言
  2. 程序名,避免更改文件名为无法找到正确的文件
  3. 版本号
  4. 更改后的时间
  5. 作者相关信息
  6. 该程序的作用,及注意事项
  7. 最后是各版本的更新简要说明

脚本示例:

1
2
3
4
5
6
7
8
9
10
11
\#!/bin/bash
\# ——————————————
\# Filename: hello.sh # Revision: 1.1
\# Date: 2018/04/01
\# Author: wangx
\# Email: wangx@gmail.com
\# Website: www.donlihuoguo.cn
\# Description: This is the first script
\# ——————————————
\# Copyright: 2018 wang
\# License: GPL echo "hello world"

脚本调试:

  • bash -n script 检查脚本的语法错误
  • bash -x script 调试脚本执行

三、变量

定义变量时,变量名不加$符号,如:

1
my_name="wangx"

变量命名规则:

  1. 数字、字母、下划线,不能以数字开头
  2. 不能使用程序中的保留字:如if,for等
  3. 做到见名知意

注意:

​ 引用变量一般需加$

​ 赋值变量:

​ name=” “ 要加引号

​ 存放多行字符时”$name”变量外加双引号可保留换行格式

bash变量的种类

局部变量、全局变量、本地变量、位置变量、特殊变量

局部变量:只在当前shell进程生效,对当前shell之外其他shell进程,包括父shell和子shell都无效

全局变量:生效范围在当前shell进程及其子进程;父进程变量可以传给子进程,子进程变量不可向上传给父进程

数字变量:$10以上的变量需要加花括号${10}

特殊变量:$1,$@,$*,$#,$0等、

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

$0:命令本身

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

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

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

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

set– 清空所有位置变量

注:怎么判断变量前加不加$符号?

如果命令能识别变量就不加$,如果命令不能识别变量加$;

养成好习惯:编完脚本将变量用unset删掉;

()中使用的命令为一次性的,小括号中相当于在子进程中执行命令

注:小括号中所说的子进程与常规的子进程不是一回事

例如:x=1;echo $$;(echo $$)中显示进程号一致

{ ;}中使用命令时在当前shell环境中执行,不开启子进程影响当前shell环境

变量运算

bash中的算术运算:help let

+,-,*,/,%取余,**乘方

实现算术运算:

  1. let var=算术表达式
  2. var=$[算术表达式]
  3. var=$((算术表达式))

注:算术运算过程中,空格尽量删除

条件测试过程中,能加空格地方尽量加空格

正则条件测试时,正则表达式不加引号

四、条件测试

测试命令:

  1. test EXPRESSION

  2. [ EXPRESSION ]

  3. [[ EXPRESSION ]] 双括号一般用于左侧字符匹配右侧扩展正则表达式

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

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

​ 若真,则返回0

​ 若假,则返回1

例如:

1
2
3
4
5
6
7
8
a=1;b=2
[ $a -eq $b ]
echo $?
结果:1
a=2;b=2
[ $a -eq $b ]
echo $
结果: 0

条件性的执行操作符

&&代表条件性的AND THEN,前面执行结果$?=0时,继续执行&&后命令

||代表条件性的OR ELSE,前面执行结果$?不为0时,执行||后命令

test 与[ ]效果相同,注意括号里内容两边需加空格

-v VAR 变量VAR是否设置

数值测试:

1
2
3
4
5
6
-gt    是否大于(greater-than)
-ge 是否大于等于(greater-than-or-equal)
-eq 是否等于(equal)
-ne 是否不等于(not-equal)
-lt 是否小于(less-than)
-le 是否小于等于(less-than-or-equal)

字符串测试:

1
2
3
4
5
6
7
8
9
10
11
12
==    是否等于
> ascii码是否大于ascii码
< 是否小于
!= 是否不等于
=~ 左侧字符串是否能够被右侧的PATTERN所匹配
注:使用PATTERN匹配时,需要加双括号[[ ]];使用扩展的正则表达式,且正则表达式不能加引号

-z 字符串是否为空,空为真,不空为假
-n 字符串是否为不空,不空为真,空为假
注:用于字符串比较时的用到的操作应该都使用引号

字符串是否为空还可用[ "$name" == "" ]来测试。

文件相关测试:

存在性测试:

1
2
-a FILE     同-e
-e FILE 文件存在性测试,存在为真,否则为假

存在性及类别测试:

1
2
3
4
5
6
7
8
-b FILE 是否存在且为块设备文件
-c FILE 是否存在且为字符设备文件
-d FILE 是否存在且为目录文件
-f FILE 是否存在且为普通文件
-h FILE 同-L
-L FILE 是否存在且为符号链接文件
-p FILE 是否存在且为管道文件
-S FILE 是否存在且为套接字文件

文件权限测试:

1
2
3
-r FILE      是否存在且有可读权限
-w FILE 是否存在且有可写权限
-x FILE 是否存在且有可执行权限

文件特殊权限测试:

1
2
3
-u FILE 是否存在且拥有suid权限
-g FILE 是否存在且拥有sgid权限
-k FILE 是否存在且拥有sticky权限

文件小测试:

1
-s FILE 是否存在且非空

文件是否打开:

1
2
3
4
-t fd:fd 文件描述符是否在终端已经打开
-N FILE 文件自从上一次被读取之后是否被修改过
-O FILE 当前有效用户是否为文件属主
-G FILE 当前有效用户是否文文件属组

注意:文件测试后跟空字符时,也反馈为True,如果要保证一个文件存在且满足测试条件时,

应表示为:

例:[ -n “file” -a -d “file” ]

file文件是否存在且为目录文件

双目测试:

1
2
3
FILE1 -ef FILE2                 FILE1是否是FILE2的硬链接
FILE1 -nt FILE2 FILE1是否新于FILE2(mtime)
FILE1 -ot FILE2 FILE1是否旧于FILE2

Bash的组合测试条件:

第一种方式:

1
2
3
COMMAND1 && COMMAND2      并且
COMMAND1 || COMMAND2 或者
!COMMAND 非

第二种方式:

1
2
3
[ EXPRESSION -a EXPRESSION ]     并且
[ EXPRESSION -o EXPRESSION ] 或者
[ !EXPRESSION ] 非

注:优先级为:”!”最高,”-a”次之,”-o”最低

短路与&&

1
2
3
4
0&&0=0
0&&1=0
1&&0=0
1&&1=1

cmd1 && cmd2

如果cmd1为假,cmd2不需要执行,反之cmd1为真,需要cmd2执行

短路或||

1
2
3
4
0||0=0
0||1=1
1||0=1
1||1=1

cmd1 || cmd2

如果cmd1为真,cmd2不需要执行,反之cmd1为假,需要cmd2执行

异或 ^

如果相同为假,反则为真

1
2
3
4
0 ^ 1 = 1
1 ^ 0 = 1
1 ^ 1 = 0
0 ^ 0 = 0

注意:[ ]和test用变量时,最好加双引号””避免出问题

1
2
3
false || { echo cmd1 ; echo cmd2 ; }

false || (echo cmd1 ; echo cmd2)

使用read命令来接受输入

read 使用read来把输入值分配给一个或多个shell变量

1
2
3
4
5
-p     指定要显示的提示
-s 静默输出,一般用于密码
-n N指定输入的字符长度N
-d ‘字符’输入结束符,类型与输入重定向的<<EOF
-t N TIMEOUT为N秒,N秒内无输入将自动退出

read命令从标准输入中读取单词,并给每个单词分配一个变量

例如:

​ read -p “Enter a filename:” FILE 标准输入将赋予变量$FILE

​ read命令从标准输入中读取单词,并给每个单词分配一个变量

read 给多个变量赋值的方法:

  1. 将多个变量输入一个文件中,用空格分开,输出重定向

    1
    read a b c < f
  2. 用”>>>”分开:

    1
    read a b c <<< "x y z"

五、配置用户环境

bash的配置文件

按生效范围划分,存在两类:

全局配置:

​ /etc/profile

​ /etc/profile.d/*.sh

​ /etc/bashrc

个人配置:

​ ~/.profile

​ ~/.bashrc

shell登录的两种方式:

​ 交互式登录:

​ 1. 直接输入账号密码登录

​ 2. su – username 切换的用户

​ 执行顺序:/etc/profile –> /etc/profile.d/*.sh –> ~/.bash_profile –> ~/.bashrc–> /etc/bashrc

​ 非交互式的登录:

​ 1. su usernme

​ 2. 图形界面打开的终端

​ 3. 执行脚本

​ 4. 任何其他的bash实例

​ 执行顺序:~/.bashrc –> /etc/bashrc –> /etc/profile.d/*.sh

注:只在交互式登录生效:/etc/profile,~/.bash_profile

配置执行文件按功能划分,存在两类:

profile类和bashrc类

Profile类:为交互式登录的shell提供配置

全局生效:/etc/profile ,/etc/profile.d/*.sh

个人生效:~/.bash_profile

功用:

  1. 用于定义环境变量

  2. 运行命令或脚本

Bashrc类:为非交互式和交互式登录的shell提供配置

全局生效:/etc/bashrc

个人生效:~/.bashrc

功用:

  1. 定义命令别名和函数
  2. 定义本地变量

修改profile和bashrc文件后使生效的两种方法:

  1. 重新启动shell进程

  2. .或sourc;例:.~/.bashrc

注: .或source执行脚本表示将在当前进程运行,而不是开启一个子进程运行(配置文件一般用此方式执行)

​ bash执行脚本则是开启一个进程执行(运行脚本一般用此方式执行)

Bash退出任务

保存在~./.bash_logout文件中(用户)

在退出登录shell时运行

可用于:

​ 创建自动备份

​ 清除临时文件

​ 清除操作历史等

特殊的变量$-

1
2
3
4
5
6
7
8
\#echo $-
\#hibBH

h:hash缓存功能;set -h,关闭hash功能;set +h,开启hash功能
i:代表交互式shell
m:打开监控模式
B:大括号扩展
H:history,命令操作历史

bash展开命令的优先级:

把命令行分成单个命令词

展开别名

展开大括号{}

展开波浪符~

命令替换$()和

再次把命令行分成命令词

展开文件通配(*、?等)

I/O重定向

运行命令

-------------本文结束感谢您的阅读-------------
0%