shell脚本基础学习

我只是一个虾纸丫 提交于 2019-11-27 15:02:13

一、shell简介

静态语言:编译型语言

C、C++、JAVA、C#

动态语言:解释型语言

边解释边执行

PHP、SHELL、python、perl

面向过程:Shell,

变量:内存空间,命名

内存:编址的存储单元

图形化界面:Gnome, KDE, Xfce

命令行界面: sh, csh, ksh, bash, tcsh, zsh

Shell 编程跟 JavaScript、php 编程一样,只要有一个能编写代码的文本编辑器和一个能解释执行的脚本解释器就可以

创建shell脚本文件:

打开文本编辑器(可以使用 vi/vim 命令来创建文件),新建一个文件 test.sh,扩展名为 sh(sh代表shell),扩展名并不影响脚本执行,见名知意就好。

执行shell脚本的方式:

1、 ./test.sh(我习惯于在当前工作目录下执行,且该文件已有执行权限,即:chmod  +x test.sh)

2、 以绝对路径的方式去执行脚本

/test/test.sh

3、直接使用bash或者sh来执行脚本

bash test.sh

sh test.sh

二、变量类型:事先确定数据的存储格式和长度

字符

数值

整型

   浮点型

bash支持的引号:

``: 命令替换

"": 强引用,可以实现变量替换

'': 弱引用,不完成变量替换

文件名通配, globbing

*: 任意长度的任意字符

?:任意单个字符

[ ]:匹配指定范围内的任意单个字符

[abc], [a-m], [a-z], [A-Z], [0-9], [a-zA-Z], [0-9a-zA-Z]

[:space:]:空白字符

[:punct:]:标点符号

[:lower:]:小写字母

[:upper:]: 大写字母

[:alpha:]: 大小写字母

[:digit:]: 数字

[:alnum:]: 数字和大小写字母

[^]: 匹配指定范围之外的任意单个字符

[[:alpha:]]*[[:space:]]*[^[:alpha:]]

练习:;

1、显示所有以a或m开头的文件;

ls [am]*

2、显示所有文件名中包含了数字的文件;

ls *[0-9]* 

ls *[[:digit:]]*

3、显示所有以数字结尾且文件名中不包含空白的文件;

ls *[^[:space:]]*[0-9]   

4、显示文件名中包含了非字母或数字的特殊符号的文件;

ls *[^[:alnum:]]*

 

三、grep, egrep, fgrep

grep: 根据模式搜索文本,并将符合模式的文本行显示出来。

Pattern: 文本字符和正则表达式的元字符组合而成匹配条件

grep [options] PATTERN [FILE...]

-i

--color

-v: 显示没有被模式匹配到的行

-o:只显示被模式匹配到的字符串

   -E: 使用扩展正则表达式

 

 

 

正则表达式: 

.: 匹配任意单个字符

[]: 匹配指定范围内的任意单个字符

[^]:匹配指定范围外的任意单个字符

字符集合:[:digit:], [:lower:], [:upper:], [:punct:], [:space:], [:alpha:], [:alnum:]

匹配次数(贪婪模式):

*: 匹配其前面的字符任意次

a, b, ab, aab, acb, adb, amnb

a*b, a\?b

a.*b

.*: 任意长度的任意字符

\?: 匹配其前面的字符1次或0次,例如:\{1\}

\{m,n\}:匹配其前面的字符至少m次,至多n次。例如:\{0,3\}

位置锚定:

^: 锚定行首,此字符后面的任意内容必须出现在行首

$: 锚定行尾,此字符前面的任意内容必须出现在行尾

^$: 空白行

 

\<或\b: 锚定词首,其后面的任意字符必须作为单词首部出现

\>或\b: 锚定词尾,其前面的任意字符必须作为单词的尾部出现

 

 

练习:

test.txt文件的内容可以由其他系统文件通过追加重定向导入(例如cat /etc/passwd >> test.txt

 

1、显示test.txt文件中以不区分大小的s开头的行;

grep -i '^s' test.txt

grep '^[sS]' test.txt

2、显示test.txt中以nologin结尾的行; 

grep ‘nologin$’ test.txt

3、显示test.txt中以#开头,且后面跟一个或多个空白字符,而后又跟了任意非空白字符的行;

grep "^#[[:space:]]\{1,\}[^[:space:]]" test.txt

4、显示test.txt中包含了:一个数字:(即两个冒号中间一个数字)的行;

grep ':[0-9]:' test.txt

5、显示/etc/inittab文件中以一个数字开头并以一个与开头数字相同的数字结尾的行;

grep '^\([0-9]\).*\1$' test.txt

扩展正则表达式:

字符匹配:

[]

[^]

次数匹配:

*: 

?:

+: 匹配其前面的字符至少1次

{m,n}

位置锚定:

^

$

\<

\>

分组:

():分组

\1, \2, \3, ...

或者

|: or

C|cat: Cat或cat, C或cat

grep -E = egrep 

 

四、逻辑运算符

逻辑:1+1>2

逻辑运算:与、或、非、异或

1: 真

0: 假

1 & 0 = 0

0 & 1 = 0

0 & 0 = 0

1 & 1 = 1

或:

非:

! 真 = 假

! 假 = 真

命令的间逻辑关系:

逻辑与: &&

第一个条件为假时,第二条件不用再判断,最终结果已经有;

第一个条件为真时,第二条件必须得判断;

逻辑或: ||

 

 

 

脚本:命令的堆砌,按实际需要,结合命令流程控制机制实现的源程序

 

测试脚本是否有语法错误:

 

bash -x 脚本:单步执行。效果如下图:

 

 

#!/bin/bash

# 注释行,不执行

/dev/null: 软件设备, bit bucket,数据黑洞

脚本在执行时会启动一个子shell进程;

命令行中启动的脚本会继承当前shell环境变量;

系统自动执行的脚本(非命令行启动)就需要自我定义需要各环境变量;

 

五、bash变量类型:

环境变量

本地变量(局部变量)

位置变量

特殊变量

变量名称:

1、只能包含字母、数字和下划线,并且不能数字开头;

2、不应该跟系统中已有的环境变量重名;

3、最好做到见名知义;

本地变量:

set VARNAME=VALUE: 作用域为整个bash进程;

局部变量:

local VARNAME=VALUE:作用域为当前代码段;

环境变量:作用域为当前shell进程及其子进程;

export VARNAME=VALUE

VARNAME=VALUE

export VARNAME“导出”

 

位置变量:

$1, $2, ...

Shift

特殊变量:

$?: 上一个命令的执行状态返回值;

程序执行,可能有两类返回值:

程序执行结果

程序状态返回代码(0-255)

0: 正确执行

1-255:错误执行,1,2,127系统预留;

$#  参数个数

$*  遍历所有参数

$@ 遍历所有参

$$  进程id

$0  脚本名称

输出重定向:

>   输出重定向

>>  输出追加重定向

2>  错误重定向

2>> 错误追加重定向

&> 完全重定向

&>>

<

<< 指定终止结束符

 

六、条件判断

bash中如何实现条件判断?

单分支if语句

if 判断条件; then

  statement1

  statement2

  ...

fi

 

双分支的if语句:

if 判断条件; then

statement1

statement2

...

else

statement3

statement4

...

fi

 

多分支的if语句:

if 判断条件1; then

  statement1

  ...

elif 判断条件2; then

  statement2

  ...

elif 判断条件3; then

  statement3

  ...

else

  statement4

  ...

fi

条件测试类型:

整数测试

字符测试

文件测试

 

条件测试的表达式:

[ expression ]

[[ expression ]]

test expression

如果test.txt文件的行数大于100,就显示big;

[ `wc -l test.txt | cut -d' ' -f1` -gt 100 ] && echo "big"

 

整数比较:

-eq: 测试两个整数是否相等;比如 $A -eq $B

-ne: 测试两个整数是否不等;不等,为真;相等,为假;

-gt: 测试一个数是否大于另一个数;大于,为真;否则,为假;

-lt: 测试一个数是否小于另一个数;小于,为真;否则,为假;

-ge: 大于或等于

-le:小于或等于

 

字符串比较:

=   等于,如:if [ "$a" = "$b" ]

==   等于,如:if [ "$a" == "$b" ], 与=等价

!=   不等于,如:if [ "$a" != "$b" ], 这个操作符将在[[]]结构中使用模式匹配.

 

 

 

练习,写一个脚本,完成以下要求:

给定一个用户:

1、如果其UID为0,就显示此为管理员;

2、否则,就显示其为普通用户;

如果 UID为0;那么

  显示为管理员

否则

  显示为普通用户

 

 

Uid.sh:

 

“引用”一个命令的执行结果,要使用命令引用;比如: 

a=`wc-l test.txt | cut -d: -f1`;

使用一个命令的执行状态结果,要直接执行此命令,一定不能引用; 

如果想把一个命令的执行结果赋值给某变量,要使用命令引用,比如USERID=`id -u user1`;

如果想把一个命令的执行状态结果保存下来,并作为命令执行成功与否的判断条件,则需要先执行此命令,而后引用其状态结果,如

id -u user1

a=$?

此句绝对不可以写为a=`id -u user1`;

 

 

练习:写一个脚本

给定一个文件,比如/etc/inittab

判断这个文件中是否有空白行;

如果有,则显示其空白行数;否则,显示没有空白行。

 

 

 

Kongbaihang.sh:

 

 

七、shell中进行算术运算:

A=3

B=6

1、let 算术运算表达式

let C=$A+$B

2、$[算术运算表达式]

C=$[$A+$B]

3、$((算术运算表达式))

C=$(($A+$B))

4、expr 算术运算表达式,表达式中各操作数及运算符之间要有空格,而且要使用命令引用

C=`expr $A + $B`

 

八、文件测试:

-e FILE:测试文件是否存在

-f FILE: 测试文件是否为普通文件

-d FILE: 测试指定路径是否为目录

-r FILE: 测试当前用户对指定文件是否有读取权限;

[ -e test.txt ]

 

九、参数传递

例如:./filetest.sh 3 4

$1: 3

$2: 4

 

练习:写一个脚本

给脚本传递两个参数(整数);

显示此两者之和,之乘积;

 

Canshu.sh:

 

 

十、字符测试、参数传递

字符测试:

==:测试是否相等,相等为真,不等为假

!=: 测试是否不等,不等为真,等为假

>

<

-n string: 测试指定字符串是否为空,空则真,不空则假

-z string: 测试指定字符串是否不空,不空为真,空则为假

 

参数传递:

练习:写一个脚本

传递一个参数(单字符就行)给脚本,如参数为q、Q、quit或Quit,就退出脚本;否则,就显示用户的参数;

 

Chuancan.sh:

 

 

十一、for循环

循环:进入条件,退出条件

for 变量 in 列表; do

  循环体

done

遍历完成之后,退出;

 

如何生成列表:

for i in{ 1..100};do

循环体

done

`seq [起始数 [步进长度]] 结束数`

例如`seq 1 2 12`

练习:写一个脚本,完成以下任务

1.创建10个系统账号user1-user10

2.设置密码是随机数(字符和数字结合)

3.将生成的账号和密码输出到一个文件中

Useradd.sh:

 

写一个脚本:

计算100以内所有能被3整除的正整数的和;

 Test.sh:

 

写一个脚本:

计算100以内所有奇数的和以及所有偶数的和;分别显示之;

 

100.sh:

 

十二、组合测试条件

-a: 与关系

-o: 或关系

!: 非关系

if [ $# -gt 1 -a $# -le 3 ]

if [ $# -gt 1 ] && [ $# -le 3 ]

 

十三、文本处理工具sed

grep, sed(流编辑器), awk 

sed基本用法:

sed: Stream EDitor

行编辑器 (全屏编辑器: vi)

sed: 模式空间

默认不编辑原文件,仅对模式空间中的数据做处理;而后,处理结束后,将模式空间打印至屏幕;

sed [options] 'AddressCommand' file ...

-n: 静默模式,不再默认显示模式空间中的内容

-i: 直接修改原文件

-e SCRIPT -e SCRIPT:可以同时执行多个脚本

-r: 表示使用扩展正则表达式

例如下图是原文件内容

 

sed  ‘s/w/a/g’ text.txt 不会修改源文件

sed  -i ‘s/w/a/g’ text.txt 第二行开头的w被改为a

 

一些使用方法:

1StartLine,EndLine

比如1,100

2/pattern1/,/pattern2/

第一次被pattern1匹配到的行开始,至第一次被pattern2匹配到的行结束,这中间的所有行

3、LineNumber

指定的行

4、StartLine, +N

startLine开始,向后的N行;

 

Command

d: 删除符合条件的行;

p: 显示符合条件的行;

a \string: 在指定的行后面追加新行,内容为string

\n:可以用于换行

 sed  '/^U/a \#hello\n#word' test.txt

 

i \string: 在指定的行前面添加新行,内容为string

   sed  '/^U/i \#hello\n#word' test.txt

w FILE: 将地址指定的范围内的行另存至指定的文件中

   sed '/^#/w /root/txt' test.txt

 

s/pattern/string/修饰符查找并替换,默认只替换每行中第一次被模式匹配到的字符串

sed 's/#/@/g' test.txt

加修饰符

g: 全局替换

将文本中的#换成@

s///=s###=s@@@

 

sed练习:

test.txt文件的内容可以由任意其他系统文件通过追加重定向导入(例如cat /etc/passwd >> test.txt

1、删除test.txt文件中行首的空白符;

sed -r 's@^[[:spapce:]]+@@g' test.txt

2、替换test.txt文件中"id:3:initdefault:"一行中的数字为5

sed 's@\(id:\)[0-9]\(:initdefault:\)@\15\2@g' test.txt

3、删除test.txt文件中的空白行;

sed '/^$/d' test.txt

4、删除test.txt文件中开头的#

sed 's@^#@@g' test.txt

5、删除某文件中开头的#号及后面的空白字符,但要求#号后面必须有空白字符;

sed -r 's@^#[[:space:]]+@@g' test.txt

6、删除某文件中以空白字符后面跟#类的行中的开头的空白字符及#

sed -r 's@^[[:space:]]+#@@g' test.txt

 

 

 

 

 

 

十四、监控某个磁盘使用率的简单脚本

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!