shell编程


本文为笔记,防止自己忘记!!!

1.shell介绍

shell是一个程序,采用c语言编写的,是用户和linux内核沟通的桥梁,它既是一种命令语言,又是一种解释性的编程语言。如下图所示:
shell作用
shell的功能如下所示:
1.命令解释功能
2.启动程序
3.输入输出重定向
4.管道连接
5.文件名置换(echo /*)
6.变量维护
7.环境控制
8.shell编程

2.shell语法

2.1 如何书写一个shell脚本

1.shell脚本的命名:命名要有一定的含义,建议一般.sh结尾
2.shell脚本的开头必须制定脚本的运行环境,以#!这个特殊的符号组成,例如:#!/bin/bash 指定该脚本解析由bin/bash来完成。
3.shell脚本的运行:第一种赋给执行权限(chmod 700 test.sh),第二种解析器直接运行,不需要赋予权限(sh test.sh)

2.2 shell中的特殊符号

1 ~ :家目录,用户的
2 !:执行历史命令; !!:执行上一条命令
3 $ :变量中取内容的符号
4 + - * / % : 加 减 乘 除 取余
5 & :后台执行
6 * :shell中的通配符,匹配所有
7 ? :shell中的通配符,匹配除回车以外的一个字符
8 ; :分号可以在shell中一行执行多个命令,命令之间用分号进行分割
9 |:管道符,上一个命令的输出作为下一个命令的输入
10 \ :转义字符,
11 `` :反引号,在命令中执行命令
12 ‘’ :单引号 脚本中的字符串需要单引号括起来,单不同于双引号的是,单引号并不解释变量
13 “” :双引号,脚本中出现的字符串可以使用双引号括起来

2.3 shell中管道的运用

在shell中很多的命令都是通过组合命令实现的,而组合命令就离不开管道符| 。

2.4 shell重定向

>  : 重定向输入 覆盖原数据
>> : 重定向追加输入,在原来数据的末尾添加
<  :重定向输入 eg:wc -l </etc/password
<< :重定向追加输入 eg:fdisk dev/sdb <<EOF ......EOF

2.5 shell的格式化输出

echo 参数:

-n :不要在最后自动换行
-e : 如果字符串中出现以下字符,则会加以特殊的处理,而不是简单的当成字符串输出
转义字符:
\a : 发出警告声
\b : 删除前一个字符
\c : 最后不加上换行符号
\f : 换行,但是光标任然留在原来的位置上
\n : 换行,且光标移至行首
\r : 光标移至行首,但不换行
\t : 插入tab
\v : 与\f相同
\  : 插入\字符
\nnn : 插入nnn(八进制)所代表的ASCII字符 

2.6 程序交互

read命令参数

默认接受来自键盘的输入,回车代表结束
-p : 打印信息
-t : 限定时间
-s : 不回显
-n : 输入字符的个数

2.7 变量

2.7.1 变量的介绍

在shell编程中,总有一些程序需要临时放入内存中,以便后面的使用,内存在系统启动的时候按照1B一个单位编号(16进制编号),并对内存的使用情况做记录,保存在内存跟踪表中。

2.7.2 变量的分类

本地变量 :用户私有的变量,只有本用户可以使用,保存在家目录下的.bash_profile、bashrc中
全局变量 : 所有用户都可以使用,保存在/etc/profile、/etc/bashrc中
用户自定义的变量 :用户自定义,比如脚本中的变量

2.7.3 变量操作

定义变量:
格式:变量=值
注意:在shell编程中,变量名和等号之间不能有空格

变量名命名规则:
	1.变量只能使用字母、数字和下划线,首个字符不能以数字开头
	2.中间不能有空格
	3.不能使用标点符号
	4.不能使用bash中的关键字
	5.定义字符时需要使用双引号或者单引号括起来

取消变量:
unset 变量名

定义全局变量:export

定义永久变量:
本地变量:用户私有的变量,只有本用户可以使用,保存在家目录下的.bash_profile、bashrc中
全局变量:所有用户都可以使用,保存在/etc/profile、/etc/bashrc中
用户自定义的变量 :用户自定义,比如脚本中的变量

2.8 数组

顾名思义,保存多个变量。

2.8.1 基本数组

可以一次存储多个变量,使用时只需要调用对应的索引就行了。

// 数组语法,中间使用空格隔开
数组名称=(元素1 元素2 元素3 。。。)
//数组赋值
//一次赋一个值
array[0]='a'
array[1]='b'
//一次赋多个值
array=('a' 'b')

//查看数组
declare -a //查看声明过的数组

//访问数组元素
array[0]  访问数组的第一个额元素
array[@]  访问数组所有的元素,等同于array[*]
#array[@]  统计数组中元素的个数
!array[@]  获取数组元素的索引
array[@]:1 从数组元素下标1开始
array[@]:1:2 从数组元素下标1开始访问两个元素

2.8.2 关联数组

关联数组允许用户自定义数组的索引

//定义
array=(name="zhangsan" age="18")

2.9 shell流程控制

2.9.1 if判断语句

Shell中的 test 命令用于检查某个条件是否成立,它可以进行数值、字符和文件三个方面的测试。

//1. 数字比较运算
-eq 等于
-gt 大于
-lt 小于
-ge 大于等于
-le 小于等于
-ne 不等于
eg:
num1=100
num2=100
if test $[num1] -eq $[num2]
then
    echo '两个数相等!'
else
    echo '两个数不相等!'
fi

//2.字符串的比较
== 等于则为真
!= 不等于则为真
-z 字符串的长度为零则为真
-n 字符串的长度不为零则为真

//3.文件的比较与检查
-d 检查文件是否存在并且为目录
-e 检查文件是否存在
-f 检查文件是否存在并且为文件
-r 检查文件是否存在且可读
-s 检查文件是否存在且不为空
-w 检查文件是否存在且可写
-x 检查文件是否存在且可执行
-O 检查文件是否存在且被当前用户拥有
-G 检查文件是否存在且为当前为当前用户组
file1 -nt file2 检查file1是否比file2新
file1 -ot file2 检查file1是否比file2旧

//4.逻辑运算
&&||!

if语法

//1.单if
if[ 条件 ] //括号的的为真执行then后面的操作
	then
fi

//2.if-then-else
if[ 条件 ]
	then commant1
else 
	commant2
fi

//3.if-then-elis
if[ 条件1]
	then commant1
elif[ 条件2 ]
	then commant2
....
else
	commant3

2.9.2 循环

for语法

//1.语法一
for var in value1 value2...
	do
	commants
done

//2.语法二,类c语法
for((变量;退出条件;自增减运算))
	do
	代码
done

//3.
continue:跳出本次循环
break:结束循环

while循环

while [ 条件 ]
	do
	代码
done

until语句
和while相反,条件为假时执行,为真时停止

until [ 条件 ]
	do
	代码
done

2.9.2 case多条件分支语句

case 变量 in
条件1)
	执行代码块1
;;
条件2)
	执行代码块2
;;
...
esac

3 shell函数

3.1 函数的语法

//语法一
函数名(){
	代码块
	return N
}

//语法二
function 函数名{
	代码块
	return N
}

3.2 正则表达式

又称规则表达式。(英语:Regular Expression,在代码中常简写为regex、regexp或RE),计算机科学的一个概念。正则表达式通常被用来检索、替换那些符合某个模式(规则)的文本。
shell中也支持正则表达式,但不是所有的命令都支持正则表达式,常见的命令有:grep、sed、awk等。
特殊字符

//定位符使用技巧,同时锚定开头和结尾,做精确匹配(即使用两个字符^和$);
//单一锚定开头和结尾,做模糊匹配(使用一个字符)
定位符:  ^    eg:^a 以a开头,默认锚定一个字符
定位符:  $    eg:a$ 以a结尾,默认锚定一个字符

eg:
^ac$:以a开头,以c结尾-----ac等等

//匹配符,匹配字符串
匹配符:
.	匹配回车以外任意字符
()	字符串分组
[]	定义字符类,匹配括号中的一个字符
[^]	否定括号内的字符,即取反
\	转义字符
|	或

eg:
^a[0-9]c$:匹配三个字符,a开头,c结尾,中间0-9
^a[^0-9]c$:匹配三个字符,a开头,c结尾,中间不是0-9的其他任何
^(a|b)c$:以a或者b开头,c结尾
//限定符
*	某个字符之后加*号,表示该字符出现0-n次
?*类似,表示该字符出现一次或不出现
++类似,表示其前面字符出现一次或多次,但必须出现一次
{n,m}	某个字符之后出现,表示该字符最少n次,最多m次
{m}	正好出现了m次

POSIX特殊字符

//
[:alnum:]	匹配任意字符字母数字0-9,a-z,A-Z
[:alpha:]	匹配任意字母a-z,A-Z
[:digit:]	数字0-9
[:graph:]	非空字符(非空格控制字符)
[:lower:]	小写字母a-z
[:upper:]	大写字母A-Z
[:cntrl:]	控制字符
[:print:]	非空字符(包括空格)
[:punct:]	标点字符
[:blank:]	空格和TAB字符
[:xdigit:]	16进制数字
[:space:]	所有空白字符(新行,空格,制表符)

4 shell对文件的操作

常用的文本编辑器有vim、nano、gedit等交互式文本编辑器,对于脚本来说无法独立完成。
为解决上述问题,linux提供了一些专门的命令,例如Perl、sed等。

4.1 sed命令

sed是linux提供的一个外部命令,它是一个行(流)编辑器,非交互式的对文件进行增删改查的操作,使用者只能在命令行输入编辑命令、指定文件名,然后在屏幕上查看输出。

//和其他编辑器的区别
一个是文本编辑器,一个是行编辑器

sed命令的数据处理原理:
sed

//sed语法
sed [options]'{commant}[flags]' [filename]
命令选项:
-e script 将脚本中的命令添加到处理输入时的执行的命令中 多条件,一行要有多个操作
-f script 将文件中指定的命令添加到处理输入时执行的命令中
-n 抑制自动输出
-i 编辑文件内容(即修改原文件)
-i.bak 修改时同时创建.bak备份文件
-r 使用扩展的正则表达式
! 取反(跟在模式条件后与shell有所区别)

//eg:
	sed -n 's/dog/cat/' data --文件执行完,不在屏幕显示自动输出(flag指定为p的还是会打印输出,即只会抑制自动输出)
	sed -e 's/dog/cat/;s/1/2/' data --包含两条s命令	
	可以将命令写到一个文件中,一个命令写一行,例如文件my_command:
	s/dog/cat/
	s/1/2/
执行时可以使用:sed -f my_command data来执行。
上述操作都是修改内存中的值,并没有修改源文件,使用-i指定,则会修改源文件。-i.bak(bak名字可以自己取)会备份源文件。

//sed常用内部命令
a	在匹配后添加
i	在匹配前添加
p	打印
d	删除
s	查找替换
c	更改
y	转换

//增加
eg:sed 'a\hello world' data --在data文件中每一行后面追加hello world 注意:第一个字符a表示命令,追加的单独占一行,并且只改变内存,不会改变原文件。
	sed '2,4a\hello world' data  --在data文件的第24行后面追加hellon world
实际中可以根据匹配对应的字符来进行指定插入的位置,语法:/匹配内容/
例如:sed '/my/a\hello world' data --在匹配到my字符后面插入hello world
//删除
//使用正则表达式方式删除文件中所有以#开头的,包含#的,以空行出现的
例如:sed -r '/(^#|#|^$)/d' data
//替换 sed 's/原内容/需要修改的内容/' 文件名
sed 's/dog/cat/' data --将文件中每行的dog修改为cat
//更改
sed 'c\hello world' data --将每一行改为hello world
sed '2,4c\hello world' data --2-4行文件修改为一行的hello world

//y 字符转换
sed 'y/a/A/' data --将所有的a转换为A
sed 'y/ab/CD/' data --所有的a转换为C,所有的b转换为D

//flags是对sed命令的一个补充
数字		表示新文本替换的模式
g		表示用新文本替换现有文本的全部实例
p		可以控制只输出你指定的内容。通常使用 p 时,还需要使用-n 选项,来屏蔽 sed 的默认输出,否则当执行命令 p 时,每行记录会输出两次。
w filename	将替换的结果写入文件
例如:
data文本的内容如下:
dog.dog.dog

sed 's/dog/cat/' data --只会将第一个dog修改为cat,如下所示:
cat.dog.dog 
使用数字可以指定替换的位置
sed 's/dog/cat/2' data --将第二个dog修改为cat
sed 's/dog/cat/g' data --将所有的dog修改为cat
sed 's/dog/cat/w new_file' --将修改的文件保存到new_file中

sed 也可以统计文本行数信息:
sed -n ‘$=’ data

4.2 awk(shell对输出流的处理)

awk是一种可以处理数据,可以产生格式化报表的语言,功能十分强大,awk认为文件中的每一行都是一条记录,
记录与记录之间的分割符为换行,每一列是一个字段,字段与字段的分隔符默认是一个或多个空格或者制表符。
awk的工作方式:读取数据,将每一行数据视为一条记录,每条记录以字段分割符分为若干字段。
// awk语法
awk [options][BEGIN]{program}[end][file]
常用命令选项:
-F 	指定描绘一行中数据字段文件分隔符,默认为空格
-f file	指定读取程序的文件名
-v	var=value,定义awk程序中使用的变量和默认值
注意:awk程序脚本由左大括号和右边大括号定义,脚本命令必须放在两个括号之间,由于awk命令行假定脚本是单文本
eg:awk	-F ":" '{print $0}' text	--打印文本中所有行的所有字段,以":"分割

//运行顺序
1.BEGIN:在开始数据流之前执行,可选项
2.program:如何处理数据流,必选项
3.END:处理完数据之后执行,必选项

4.2.1 对字段列的提取

提取一个文本中的一列数据,并打印输出

//字段相关内置变量
$0	表示整行文本
$1	表示文本行的第一个数据字段
$2	表示第二个数据字段
...
$NF	表示文本行的最后一个字段
eg:d
awk {print $1} text	--打印text文本每一行的第一个数据字段

//指定行号
NR	指定行号
eg:awk 'NR==3{print $0}' text	--打印第三行的所有字段
awk	'NR==3{print $1 "_" $2 "_" $3}' text	--print命令中间可以加字符串,如上拼接了"_"

4.2.3 awk程序的优先级

//BEGIN
在program执行前执行,不需要数据源即可以执行。
eg: awk 'BEGIN{print "hello world"}'
由上可知,在没有指定数据源的前提下,依然可以打印hello world

//END 同理

4.2.4 awk其他用法

// 定义数组
定义的方式:awk 数组名[索引]=值
eg:awk 'BEGIN{array[0]=100;array[1]=200;print array[0],array[1]}'
输出为:100 200

//awk运算
赋值运算		=
比较运算		>,>=,==,<=,!=
数学运算		+,-,*,/,%,**,++,--
逻辑运算		&&,||

//awk的环境变量
FIELDWIDTHS	以空格分割的数字列表,用空格定义每个数据字段的精确宽度
FS	输入字段的分割符号
OFS	输出字段分割符号
RS	输入记录分割符
ORS	输出记录分隔符

eg:awk	'BEGIN{FIELDWIDTHS="5,2,8"}NR==1{print $1,$2,$3}' /etc/password
输出结果:root: x: 0:0:root (长度分别为5 2 8)

awk	'BEGIN{FS=":"}NR==1{print $0}' /etc/password	(此用法和上面使用-F效果一样)

awk	'BEGIN{FS=":",OFS="_"}NR==1{print $1,$2}' data	(输出数据之间的分隔符为_)	

4.2.5 awk的流程控制

//if判断语句 if 条件 语句;else 语句
eg:awk	'{if($1)>5 print $1}' data

//for循环
for(int i =0; i<n; i++){语句}

//while循环
while(条件){语句}

//do while循环
do{语句}while(条件)
注意:循环中的breakcontinue都能正常使用。
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值