shell编程语法

知识的领域是无限的,我们的学习也是无限期的。这篇文章主要讲述shell编程语法相关的知识,希望能为你提供帮助。
1.shell编程

shell编程:过程式.解释执行
#编程语言的基本结构:
各种系统命令的组合
数据存储:变量.数组
表达式:a + b
语句:if

2.shell脚本
shell脚本:
包含一些命令或声明,并符合一定格式的文本文件
格式要求:首行shebang机制
#!/bin/bash
#!/usr/bin/python
#!/usr/bin/perl

#shell脚本的用途有:
自动化常用命令
执行系统管理和故障排除
创建简单的应用程序
处理文本或文件

3.创建shell脚本
#第一步:使用文本编辑器来创建文本文件
第一行必须包括shell声明序列:#!
示例:#!/bin/bash
添加注释
注释以#开头
#第二步:运行脚本
给予执行权限,在命令行上指定脚本的绝对或相对路径
直接运行解释器,将脚本作为解释器程序的参数运行

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

#脚本的基本结构
#!SHEBANG
CONFIGURATION_VARIABLES
FUNCTION_DEFINITIONS
MAIN_CODE

#shell脚本示例
#!/bin/bash
# ------------------------------------------
# Filename: hello.sh
# Revision: 1.1
# Date: 2017/06/01
# Author: test
# Email: test@gmail.com
# Website: www.test.com
# Description: This is the first script
# Copyright: 2017 test
# License: GPL
# ------------------------------------------
echo "hello world"

5.脚本调试
#检测脚本中的语法错误
bash -n /path/to/some_script
#调试执行
bash -x /path/to/some_script

6.变量
变量:命名的内存空间
#作用:
1.数据存储方式
2.参与的运算
3.表示的数据范围

#类型:
字符
数值:整型/浮点型

静态编译语言:使用变量前,先声明变量类型,之后类型不能改变,在编译时检查,如:java,c
动态编译语言:不用事先声明,可随时改变类型,如bash,Python

强类型语言:不同类型数据操作,必须经过强制转换,同一类型才能运算,如java , c# ,python
如:以下python代码
print(test+ 10) 提示出错,不会自动转换类型
print(test+str(10)) 结果为test10,需要显示转换类型
弱类型语言:语言的运行时会隐式做数据类型转换。无须指定类型,默认均为字符型; 参与运算会自动进行隐式类型转换; 变量无须事先定义可直接调用
如:bash 不支持浮点数,php,javascript

6.1.Shell中变量
#Shell中变量命名法则:
1.不能使程序中的保留字:例如if, for
2.只能使用数字.字母及下划线,且不能以数字开头
3.见名知义
4.统一命名规则:驼峰命名法(大驼峰:第一个字母大写,后边也大写;小驼峰:第一个字母小写,后边大写)
#Shell中命名建议规则:
1.变量名大写
2.局部变量小写
3.函数名小写
4.用英文名字,并体现出实际作用

6.2.变量的种类
根据变量的生效范围等标准划分下面变量类型
1)局部变量:生效范围为当前shell进程; 对当前shell之外的其它shell进程,包括当前shell的子shell进程均无效
2)环境变量:生效范围为当前shell进程及其子进程
3)本地变量:生效范围为当前shell进程中某代码片断,通常指函数
4)位置变量:$1, $2, ...来表示,用于让脚本在脚本代码中调用通过命令行传递给它的参数
5)特殊变量:$?, $0, $*, $@, $#,$$

$- 显示shell使用的当前选项,与set命令功能相同
$# 添加到Shell的参数个数
$0 Shell本身的文件名
$* 所有参数列表; "$*" 以"$1 $2 … $n"的形式输出所有参数
$@ 所有参数列表; "$@" 以"$1" "$2" … "$n" 的形式输出所有参数
$? 最后运行的命令的结束代码; 0表示没有错误,其他任何值表明有错误
$! Shell最后运行的后台Process的PID
$$ Shell本身的PID

6.2.1.局部变量
变量赋值:name=value
可以使用引用value
(1) 可以是直接字串:name="root"
(2) 变量引用:name="$USER"
(3) 命令引用:name=`COMMAND`
name=$(COMMAND)

变量引用:$name 或者 $name
" " 弱引用,其中的变量引用会被替换为变量值
强引用,其中的变量引用不会被替换为变量值,而保持原字符串
显示已定义的所有变量:set
删除变量:unset name

6.2.2.环境变量
#变量声明、赋值:
export name=VALUE
declare -x name=VALUE

#变量引用:
$name, $name

#显示所有环境变量:
env
printenv
export
declare -x

#删除变量:
unset name

#bash内建的环境变量
PATH
SHELL
USER
UID
HOME
PWD
SHLVL
LANG
MAIL
HOSTNAME
HISTSIZE
_下划线

6.2.3.位置变量
位置变量:在脚本代码中调用通过命令行传递给脚本的参数
$1, $2, ... 对应第1、第2等参数,shift [n]换位置

set -- 清空所有位置变量

6.2.4.只读变量
只读变量:只能声明,但不能修改和删除
声明只读变量:
readonly name
declare -r name
查看只读变量:
readonly -p

7.退出状态
进程使用退出状态来报告成功或失败
0 代表成功,1-255代表失败
$? 变量保存最近的命令退出状态
例如:
ping -c1 -W1 hostdown & > /dev/null
echo $?

bash自定义退出状态码
exit [n]:自定义退出状态码
注意:脚本中一旦遇到exit命令,脚本会立即终止; 终止退出状态取决于exit命令后面的数字
注意:如果未给脚本指定退出状态码,整个脚本的退出状态码取决于脚本中执行的最后一条命令的状态码

8.表达式8.1.算术运算
bash中的算术运算:help let
+, -, *, /, %取模(取余), **(乘方),乘法符号有些场景中需要转义
实现算术运算:
(1) let var=算术表达式
(2) var=$[算术表达式]
(3) var=$((算术表达式)) #在 $(( )) 中的变量名称,可于其前面加 $ 符号来替换,也可以不用
(4) var=$(expr arg1 arg2 arg3 ...)
(5) declare –i var = 数值
(6) echo 算术表达式 | bc
bash有内建的随机数生成器变量:$RANDOM(0-32767)
示例:生成 0 - 49 之间随机数
echo $[$RANDOM%50]

进制转换
$(( ))可以将其他进制转成十进制数显示出来。用法如下:
echo $((N#xx))
其中,N为进制,xx为该进制下某个数值,命令执行后可以得到该进制数转成十进制后的值
echo $((2#110)) # 二进制转十进制
6
echo $((16#2a)) #十六进制转十进制
42
echo $((8#11))#八进制转十进制
9

8.2.赋值运算
增强型赋值:
+=, -=, *=, /=, %=
#let varOPERvalue
例如:let count+=3
自加3后自赋值
#自增,自减:
let var+=1
let var++
let var-=1
let var--

8.3.逻辑运算
【shell编程语法】true(1), false(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 ! true
! 0 = 1 ! false

#短路运算
#短路与
第一个为0,结果必定为0
第一个为1,第二个必须要参与运算
#短路或
第一个为1,结果必定为1
第一个为0,第二个必须要参与运算
#异或:^
异或的两个值,相同为假,不同为真
1^1=0
0^0=0
1^0=1
0^1=1

8.4.条件测试
判断某需求是否满足,需要由测试机制来实现
专用的测试表达式需要由测试命令辅助完成测试过程
评估布尔声明,以便用在条件性执行中
? 若真,则返回0
? 若假,则返回1
#测试命令:
test EXPRESSION
[ EXPRESSION ]
[[ EXPRESSION ]]

  注意:EXPRESSION前后必须有空白字符
8.4.1.数值测试
-v VAR变量VAR是否设置
#数值测试:
-gt 是否大于#greater than
-ge 是否大于等于

-eq 是否等于
-ne 是否不等于

-lt 是否小于#less than
-le 是否小于等于

8.4.2.字符串测试
#字符串测试:
=是否等于
> ascii码是否大于ascii码
< 是否小于
!=是否不等于
=~左侧字符串是否能够被右侧的PATTERN所匹配
#注意: 此表达式一般用于[[ ]]中; 扩展的正则表达式

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

8.4.3.文件存在测试
#存在性测试
-a FILE: 同 -e
-e FILE: 文件存在性测试,存在为真,否则为假

#存在性及类别测试
-b FILE:是否存在且为块设备文件
-c FILE:是否存在且为字符设备文件
-d FILE:是否存在且为目录文件
-f FILE:是否存在且为普通文件
-h FILE或 -L FILE:存在且为符号链接文件
-p FILE:是否存在且为命名管道文件
-S FILE:是否存在且为套接字文件

8.4.4.文件权限测试
#文件权限测试:
-r FILE:是否存在且可读
-w FILE: 是否存在且可写
-x FILE: 是否存在且可执行

#文件特殊权限测试:
-u FILE:是否存在且拥有suid权限
-g FILE:是否存在且拥有sgid权限
-k FILE:是否存在且拥有sticky权限

8.4.5.文件属性测试
#文件大小测试:
-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

    推荐阅读