Bootstrap

Shell 脚本详解

简介

shell :蛋、壳。shell脚本是在操作系统外,可以直接调用系统内核命令的一个脚本语言。

shell脚本可以分为两大类组成:

	1.命令行 (系统命令行)
	2.脚本语法 (编程语言的基本语法)

1.命令行:可以直接和系统内核进行交换使用

2.脚本语法:编程语言的语法类似,可以实现对命令行更复杂的设计,通过脚本语言实现更复杂的功能

很多shell脚本的书,更多侧重去介绍Shell脚本语法方面的内容,部分结合命令行来讲述。

一、命令行

我们常用的终端一般打开之后,会自动登录一个默认的shell。我们也可以使用不同的shell,使用cat /etc/shells查看支持的shell
例如:

Linux

/bin/sh
/bin/bash
/usr/bin/sh
/usr/bin/bash

Mac

/bin/bash
/bin/csh
/bin/dash
/bin/ksh
/bin/sh
/bin/tcsh
/bin/zsh

shell中存在父进程和子进

fork-exec模型

1.常用基本命令

ls 命令- 显示指定目录下的文件及属性信息
cd 命令 - 切换目录
mkdir 命令 - 创建目录文件
mv 命令 - 移动或修改文件
cp 命令 - 复制文件或目录
pwd 命令 - 显示当前目录的绝对路径
find 命令 - 查找文件

其他命令随后慢慢补充

2.shell文件三剑客(grep、sed、awk)

1).grep 命令 - 强大的文本搜索工具

grep 是一个强大的文本搜索工具,不仅支持单个匹配搜索,而且支持多个和正则匹配的搜索。

# man grep

The grep utility searches any given input files, selecting lines that match
     one or more patterns.  By default, a pattern matches an input line if the
     regular expression (RE) in the pattern matches the input line without its
     trailing newline.  An empty expression matches every line.  Each input line
     that matches at least one of the patterns is written to the standard
     output.

常用的使用参数如下:

参数详细解释
-i忽略大小写
-c只输出匹配行的数量
-l只李处符合匹配的文件名,不列出具体的匹配行
-n李处所有的匹配行,显示行号
-h查询多文件时不显示文件名
-W匹配证词
-X匹配整行
-r递归搜索
-F匹配固定字符串的内容
-E支持扩展的正则表达式

更具体的参数可以参考系统内的man文档

2)sed命令 - 批量编辑文本文件

sed命令来自“Stream editor”的缩写,其功能是用于利用语法/脚本对文本文件进行批量的编辑操作(删除
替换、添加、移动等),最后输出所有行或者仅输出处理的某些行,sed可以在无交互的情况下实现复杂的文本处理。

sed的工作主要包括读取、执行和显示三哥过程

  • 读取: sed从输入流(文件、管道、标准输入)中读取一行内容并存储到临时的缓冲区中(又称模式空间)
  • 执行: 默认情况下,所有的sed命令都在模式空间中顺序执行,除非指定了行的地址,否则sed命令将会在所有的行上依次执行
  • 显示: 发送修改后的内容到输出流,在发送数据后,模式空间将被清空

**注意:**默认情况下所有的 sed 命令都是在模式空间内执行的,因此输入的文件并不会发生任何变化,除非是用重定向存储输出。

The sed utility reads the specified files, or the standard input if no
     files are specified, modifying the input as specified by a list of
     commands.  The input is then written to the standard output.

基本语法

通常情况下调用sed命令有两种格式,其中 “参数”是操作目标文件,当存在多个操作对象时应,文件之间用逗号“,”分隔;而scriptfile表示脚本文件,需要用“-f”选项指定,当脚本文件出现目标之前,表示通过指定的脚本文件来处理输入的目标文件。

sed [选项] '' 参数
sed [选项]  -f scriptfile 参数
常见的Sed命令选项
参数详细解释
-e 或 -expression=:表示用指定命令或者脚本来处理输入的文本文件
-f 或 -file=表示用哪个指定的脚本文件处理来输入的文件文件
-h 或 -help显示帮助
-n、-quiet或、silent表示仅显示处理后的结果
-i直接编辑文本文件
常见的操作

操作用于指定对文件操作的动作行为,通常情况下采用的“[ n1 [, n2 ] ]”操作参数的格式。n1、n2是可选的,不一定会存在,代表选择进行操作的行数,如操作需要在5~20行之间进行,则表示为“5, 20动作行为”

操作参数参数的说明
a增加, 在当前行下面增加一行指定的内容
c替换,将选定行替换为指定内容
d删除, 删除选定的行
i插入,在选定行上面插入一行指定内容
p打印,如果同时指定行,表示打印指定行;如果不指定行,则表示打印所有内容;如果有非打印字符,则以ASCII码输出。其中常与“-n”选项一起使用
s替换,替换指定字符
y字符转化

awk命令 - 一种处理文本文件的语言,一个强大的文本分析工具

AWK是一种处理文本文件的语言,是一个强大的文本分析工具。
它是专门为文本处理设计的编程语言,也是行处理软件,通常用于扫描、过滤、统计汇总工作
数据可以来自标准输入也可以是管道或文件

Awk scans each input file for lines that match any of a set of patterns
       specified literally in prog or in one or more files specified as -f
       progfile.  With each pattern there can be an associated action that will
       be performed when a line of a file matches the pattern.  Each line is
       matched against the pattern portion of every pattern-action statement;
       the associated action is performed for each matched pattern.  The file
       name - means the standard input.  Any file of the form var=value is
       treated as an assignment, not a filename, and is executed at the time it
       would have been opened if it were a filename.  The option -v followed by
       var=value is an assignment to be done before prog is executed; any number
       of -v options may be present.  The -F fs option defines the input field
       separator to be the regular expression fs.

       An input line is normally made up of fields separated by white space, or
       by the regular expression FS.  The fields are denoted $1, $2, ..., while
       $0 refers to the entire line.  If FS is null, the input line is split
       into one field per character.

       A pattern-action statement has the form:

              pattern { action }
        A missing { action } means print the line; a missing pattern always
       matches.  Pattern-action statements are separated by newlines or
       semicolons.

       An action is a sequence of statements.  A statement can be one of the
       following:

              if( expression ) statement [ else statement ]
              while( expression ) statement
              for( expression ; expression ; expression ) statement
              for( var in array ) statement
              do statement while( expression )
              break
              continue
              { [ statement ... ] }
              expression              # commonly var = expression
              print [ expression-list ] [ > expression ]
              printf format [ , expression-list ] [ > expression ]
              return [ expression ]
              next                    # skip remaining patterns on this input line
              nextfile                # skip rest of this file, open next, start at top
              delete array[ expression ]# delete an array element
              delete array            # delete all elements of array
              exit [ expression ]     # exit immediately; status is expression

选项

awk [选项] ‘模式条件{操作}’ 文件1 文件2....
awk -f|-v 脚本文件 文件1 文件2.....

内置变量

  • FS:指定每行文本的字段分隔符,缺省为空格或制表位(tab)
  • OFS:输入字段的分割符(默认是空格)
  • NF:当前处理的行的字段个数
  • NR:当前处理的行的行号(序数)
  • FNR:读取文件的记录行号(从1开始,若读取新的文件依旧是从1开始)
  • ORS:输出行的分割符,默认为换行符
  • RS:行分隔符,根据RS的定义把资料切割成许多条记录
  • $0:当前处理的行的整行内容
  • $n:当前处理行的第n个字段(第n列)

2.其他

二、脚本语法

shell 脚本首行一般都会以 #!/bin/bash开始,这个是说明脚本是采用那种shell来执行的。

编程语言一般分为:解释型和编译型两种,而shell脚本和解释型语言类似。

1.变量

1).声明变量

使用语句“变量名=值”为变量赋值的同时,变量就会自动创建

2).引用变量

在引用变量的值时,需要在变量名前面加上前缀$
1)变量名和字符串之间的分隔符
2)使用{}明确区分变量名和字符串

其中变量参数使用

位置变量作用描述
$0获取当前执行的shell脚本的文件名,如果执行脚本包含路径,那么包含脚本路径
$n获取当前执行的shell脚本的第n个参数,n=1…9, 当您为0时表示脚本的文件名,如果n大于9,则用大括号括起来
$#获取当前执行的shell脚本后面接的参数总个数
$*获取当前shell脚本所有传参的参数,不加引号和$@相同,如果给$加上双引号,例如:“$”,则表示将所有的参数视为单个字符串,相当于$1$2$3
$@获取当前shell脚本所有传参的参数,不加引号和$*相同,如果给$@加上双引号,例如:“$@”,则表示将所有的参数视为不同的独立个字符串,相当于$1 $2 $3 …,将多参数传递给其他程序的最佳方式。

字符串变量的字串使用说明
请添加图片描述

□#表示从开头删除匹配最短。
□##表示从开头删除匹配最长。
□%表示从结尾删除匹配最短。
□%%表示从结尾删除匹配最长。
□ac表示匹配的字符串,表示匹配所有,ac匹配开头为a、中间为任意多个字符、结尾为c的字符串。
□a
C表示匹配的字符串,表示匹配所有,aC匹配开头为a、中间为任意多个字符、结尾为C的字符串。

2.控制结构

hash中常用if、for、case、while、until等语句

控制结构中的判断语句的内容

1).[] 是test 命令(其中 [] 和 [[]]使用方法类似)

当[命令的参数为各种运算符时,可以比较字符串或数值,或者判断文件是否存在。如果判断结果为真,则[命令返回的退出状态码为0,否则为1。需要牢记的是,shell脚本中并没有常见编程语言中的true或者false这样的布尔类型,它用的都是退出状态码。

字符串比较
str1 和 str2 是两个变量字符串

运算符说明
str1 = str2str1和 str2 相等 (与 == 相同)
str1 == str2str1和 str2 相等 (与 = 相同)
str1 != str2str1和 str2 不相等
-n str1str1为非空字符串
-z str1str1为空字符串
str1 < str2str1比 str2在字典顺序上更靠前
str1 > str2str1比 str2 在字典顺序上更靠后
str1=abc
str2=xyz

if ["$str1" = "$str2"]; then
	echo 'str1 等于 str2'
else
	echo 'str1 不等于 str2'
fi

整数比较
int1 和int2 表示任意整数

运算符说明
int1 -eq int2int1 和 int2 相等
int1 -ne int2int1 和 int2 不相等
int1 -lt int2int1 小于 int2
int1 -le int2int1 小于等于 int2
int1 -gt int2int1 大于 int2
int1 -ge int2int1 大于等于 int2

文件属性判断
file表示的是 判断的文件

运算符说明
-a filefile存在(与 -e 相同)
-d filefile存在,且类型为目录
-f filefile存在,且类型是普通文件
-s filefile存在,且文件大小大于0
-e filefile存在(与 -a 相同)
…………
#!/bin/bash
file="$1"

if [-e "$file"]; then
	echo "file 存在"
else
	echo "file 不存在"
fi

一些组合使用方式,使用期间在详细查看

&& 和 ||是两个和test命令相关的语法,可以通过这两个组合复杂的组合方式。

2)常用语句

if语句结构

if 条件; then
		当条件为真时执行的程序
fi

在if语句中使用elif语句或else语句的结构

if 条件1; then
	条件1为真执行的条件语句
elif 条件2;then
……
elif 条件3;then
……
else
	剩余条件
fi

For

for用于循环处理单词列表的语法, 其中for语言中还有break 和 continue 一起使用,break和 continue 的使用和其他编译语言

for 变量 in 列表变量
do
	循环处理
done


#例子
#!/bin/bash
for i in aaa bbb ccc
do
	echo $i
done	
case

case语句会使用多个模式去匹配一个字符串,并根据匹配结果执行相应的处理

case 变量 in
	模式1)
		处理方法
	;;
	模式2)
		处理方法
	;;
	
while 和 until

while 和 until 执行条件类似,但判断条件相反

while 命令
do
	循环处理
done

3.重定向和管道

1.重定向

shell在执行命令时可以修改标准输入的输入源和标准输出的目标位置。这个功能称为重定向。

file是一个文件

操作符说明
< file使用file作为标准输入
> file使用file作为标准输出
>> file将标准输出追加到file文件尾部
2>| file忽略noclobber,将标准输出重定向到file文件
2> file使用file作为白哦准错误输出
2>> file将标准错误输出追加到file文件末尾
2 >| file忽略noclobber,将标准错误输出重定向到file文件
>& m将标注输出设置位文件描述m的副本
n >& m将文件描述n设置位文件描述符m的副本
&> file将标准输出和标准错误输出统一输出到file文件
&>> file将标准输出和标准错误统一追加到file文件末尾

2.管道

命令的输出内容除了可以重定向到文件,哈可以作为其他命令的输入使用,这一功能称为管道。(管道之后换行不会破坏管道的连续性)

命令1 | 命令2


使用重定向实现管道功能(每次都要使用一个临时文件才能实现管道功能,而且会存在文件覆盖等问题,比较繁琐)

#管道方法
ls | less

#使用 重定向方法实现管道功能
ls > result.txt
less < result.txt

使用( )和{ }的方式把多个命令进行组合,同时进行重定向(管道)进行组合使用。

4.函数

函数:用于实现某一功能高度关联的或者需要重复执行的处理合并在一起,可以提高代码的可读性。在Shell脚本中参数可以使用位置参数**$1,$2,……**

5.内置命令

1):命令

:(冒号)是一个特殊的命令,它不做任何处理,并且永远将0作为退出状态码,也被称为空命令(null command),也就是永远为true

2)echo命令

echo命令用于将参数中指定的字符串输出到标准输出,如果指定了多个参数,它会使用空格将各个参数连接起来并输出

命令描述
-n-n选项用于设置不让脚本输出行尾的换行符
-e-e 是将字符串中的转义符号按照标准输出
-E-E 是 -e相反的意思,忽略转义符号
3)printf命令

printf是一个根据输出格式将字符串输出到标准输出的命令。它和C语言等编程语言中的printf函数类似

# 语法
 printf 格式字符串 参数1 参数2 ……

printf '%d - %s degress\n' "$value" "$city"
4)pwd 和 cd

pwd 命令返回绝对路径形式的当前目录

pwd提供了-P和-L两个选择

-P选项且当前目录下有符号链接,那么在输出结果时,符号链接会被转换为物理路径

指定了-L选项,则直接输出符号链接本身

cd命令用于将当前路径切换为参数指定的目录

在指定了-P选项时,目标路径中如果包含符号链接,符号链接就会转换为相应的物理路径,并且当前工作路径会切换到该路径。如果指定了-L选项或没有指定任何选项,则不会对路径中的符号链接执行任何处理,进入带有符号链接的路径。
5)type命令

type命令用于判断指定的命令的类型。该命令可以输出参数中命令的类型,即别名、保留字、函数、内置命令、可执行文件中的任意一个。

6)shift命令

shift命令用于移动位置参数的编号。运行shift命令后,$1的内容将消失,$2变成$1,$3变成$2,每个位置参数都向左移动1位

7)set命令

set是一个比较复杂的命令,有3个功能。

第1个功能是显示当前shell中的所有变量。如果在执行set命令时没有指定任何参数,那么该命令就会输出当前shell中设置的变量及其值的列表,以及函数名和函数体的列表。

set命令的第2个功能是开启或关闭shell的各种选项。这要通过“set -o选项名称”的形式使用。比如,设置了set -o verbose,就相当于开启了verbose选项。在这之后的shell会在命令执行之前,先输出将要执行的命令行的内容。

set命令的第3个功能是设置位置参数。如果set命令后面的参数不是其选项,该参数的值就会被用来设置相应的位置参数并覆盖原来已有的位置参数。如果set后面指定了多个参数,那么就会像$1, $2, $3, …这样按顺序为位置参数赋值。

8)unset命令

unset命令用于删除shell中的变量。使用方法为“unset变量名

9)read命令

read命令用于从标准输入读取一行数据

read 变量1 变量2 ……

10)trap命令

trap命令用于捕捉发送给当前进程的信号。信号是Linux系统中用于进程间通信的一种机制,我们可以通过键盘操作或者kill命令发送信号。

11)wait命令

wait命令用于等待在后台运行的进程的结束。在以后台的方式运行比较耗时的处理时,如果想等待所有处理结束,就可以使用wait命令。

12)exec命令

exec命令可以启动参数中指定的命令

13)eval命令

eval命令可以将参数指定的字符串当作shell的命令行解析并执行

Linux正则表达式及三剑客命令(grep、sed、awk)

网络服务包括但不限于:Crond、Rsync、Inotify、Nginx、PHP、MySQL、Keepalived、Memcached、Redis、NFS、Iptables、SVN、Git

;