Shell基本知识及常用命令

本文介绍Shell的基本知识和常用命令,包括diff,patch,cut,&&和||,sort,uniq,test,tr以及$相关的shell命令。

一、Shell基本知识

1.1 什么是shell
  1. shell
    shell也是操作系统中的一个软件,它包在 linux 内核的外面,为用户和内核之间的交互提供了一个接口,系统中的命令用 shell 去解释 shell 接收系统回应的输出并显示其到屏幕上;
    可以将 Shell 终端解释器当作人与计算机硬件之间的“翻译官”它作为用户与 Linux 系统内部的通信媒介,除了能够支持各种变量与参数外,还提供了诸如循环、分支等高级编程语言才有的控制结构特性。
  2. shell 脚本
    脚本是一种解释型语言
    用shell脚本保存执行动作
    用脚本判定命令的执行条件
    用脚本来实现动作的批量执行
    shell script (程序化脚本) 是利用 shell 的功能所写的一个“程序 (program)”,这个程序是使用纯文本文件,将一些 shell 的语法与指令(含外部指令)写在里面, 搭配正则表达式、管线命令与数据流重导向等功能,以达到我们所想要的处理目的。
1.2 shell脚本格式

Shell 脚本文件的名称可以任意,但为了避免被误以为是普通文件,建议将 .sh 后缀加上,以表示是一个脚本文件。
shell 脚本中一般会出现三种不同的元素:
第一行的脚本声明(#!)用来告诉系统使用哪种 Shell 解释器来执行该脚本;
第二行的注释信息(#)是对脚本功能和某些命令的介绍信息,使得自己或他人在日后看到这个脚本内容时,可以快速知道该脚本的作用或一些警告信息;
第三、四行的可执行语句也就是我们平时执行的 Linux 命令了。

脚本声明和注释信息系统自动添加方式

在/etc/vimrc 中加入如下内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
autocmd BufNewFile *.sh exec ":call SetComment_sh()"
" 表示当通过 vim 编辑任何以 .sh 结尾的文件时,都会在文件开头实现对如下 Bleach() 内容的调用
func SetComment_sh()
call setline(1,"#!/bin/bash")
call setline(2,"")
call setline(3, "#================================================================")
call setline(4, "# Copyright (C) ".strftime("%Y")." Sangfor Ltd. All rights reserved.")
call setline(5, "# ")
call setline(6, "# 文件名称:".expand("%:t"))
call setline(7, "# 创 建 者:Mxsenn")
call setline(8, "# 创建日期:".strftime("%Y年%m月%d日"))
call setline(9, "# 描 述:")
call setline(10, "#")
call setline(11, "#================================================================")
call setline(12, "")
call setline(13, "")
endfunc

退出保存后,编辑任意以.sh结尾的文件,自动添加如上内容。

1.3 脚本的调试

sh -x scritps.sh 适用于所有shell脚本
vim scripts.sh shell脚本必须有X权限

#!/bin/bash -x

1.4 脚本的执行
  • sh script.sh
  • source script.sh
  • . script.sh
  • chmod +x script.sh
  • ./script.sh

二、Shell脚本常用命令

2.1 diff

diff是用在比对两个文件之间的差异的,并且是以行为单位来比对的。一般是用在 ASCII 纯文本文件的比对上。由于是以行为比对的单位,因此 diff 通常是用在同一文件(或软件)的新旧版本差异上对比上,能够借由 diff 创建的分析档,以处理补丁(patch)功能的文件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
[root@mxsenn ~]# diff  将两个文件或目录的内容进行比较
-b:忽略一行当中,仅有多个空白的差异(例如"about me"与"about me"视为相同)
-B:忽略空白行的差异。
-i:忽略大小写的不同。
-u:显示文件信息的不同
显示内容的含义
[num1,num2][a|b|c][num3,num4]
num1,num2 #表示在第一个文件中的行数
num3,num4 #表示在第二个文件中的行数
a #表示添加---add
c #表示更改---change
d #表示删除---delete
< #表示第一个文件中的内容,
> #表示第二个文件中的内容
--- #分割线
如新建两个文件 test1 test2
test1 内容为:第一行 hello;第二行 linux
test2 内容为:第一行 hello;第二行 unix
用 diff 比较两文件内容的不同
[root@mxsenn shell]# diff test1 test2 #比较文件内容的不同
2c2 #左边文件的第二行被取代(c)成右边文件的第二行,两个文件内容就会相同
< linux #左边文件第二行内容
--- #分割线
> unix #右边文件第二行内容
[root@mxsenn shell]# diff -u test1 test2
--- test1 2018-06-25 11:42:01.054285062 +0800
#test1 test2 文件的信息
+++ test2 2018-06-25 11:42:14.494316842 +0800
@@ -1,2 +1,2 @@
#新旧文件要修改数据的界定范围,旧文件在 1-2 行,新文件在 1-2 行
hello
-linux #删除linux
+unix #加上unix

diff还可以用来比较目录

1
2
3
4
5
6
7
[root@mxsenn shell]# diff -r /etc/rc0.d/ /etc/rc5.d/
# -r:递归地比较找到的任何子目录
Only in /etc/rc0.d/: K03rhnsd #此文件只在/etc/rc0.d 中有
Only in /etc/rc0.d/: K90network #此文件只在/etc/rc0.d 中有
Only in /etc/rc5.d/: S10network #此文件只在/etc/rc5.d 中有
Only in /etc/rc5.d/: S97rhnsd #此文件只在/etc/rc5.d 中有
这样就比较出了两目录内容的不同
2.2 patch

这个指令常与 diff 配合使用,该命令的作用就是我们俗称的打补丁。

1
2
3
4
5
6
7
8
9
[root@mxsenn ~]# yum install patch -y  #首先安装 patch
[root@mxsenn ~]# patch
-p :后面可以接“取消几层目录”的意思。
-R :代表还原,将新的文件还原成原来旧的版本
-b :备份文件。在修补文件时,重命名或复制原始文件,而不是删除它,默认在原文件名称上加.orig后缀
[root@mxsenn shell]# diff -u test1 test2 > test.patch
#生成补丁文件 test.patch
[root@mxsenn shell]# patch -b test1 test.patch
patching file test1 #修补文件test1

通过查看上述test1、test2、test1.orig这三个文件可得:上述操作先生成了test1到test2转变过程的patch文件,然后执行patch -b test1 test.patch给test1文件打补丁,此时test1的内容就变成了test2,而由于添加了-b参数所以保留了test1的源文件,只不过文件名加了后缀.orig,查看test1.orig的文件内容则是原来test1的文件内容。

2.3 cut

cut 命令用于按“列”提取文本字符,格式为“cut [参数] 文本”。

1
2
3
4
5
6
7
8
9
[root@mxsenn ~]# cut -d '分隔字符' -f 设置需要看的列数
[root@mxsenn ~]# cut -c 字符区间用于排列整齐的讯息
选项与参数:
-d :后面接分隔字符。与 -f 一起使用;
-f :依据 -d 的分隔字符将一段讯息分区成为数段,用 -f 取出第几段的意思;
-c :以字符 (characters) 的单位取出固定字符区间;
示例:截取主机的 ip 地址
[root@mxsenn ~]# ifconfig | head -n 2 | tail -n 1 | cut -d " " -f 10
#截取主机的 ip 地址,以‘空格’为分隔符,截取第 10 列
2.4 &&和||
  • &&
    在 Shell 终端中逻这里写代码片辑“与”的运算符号是&&,它表示当前面的命令执行成功后才会执行它后面的命令
  • ||
    在 Shell 终端中逻辑“或”的运算符号是 ||,表示当前面的命令执行失败后才会执行它后面的命令。
1
2
3
4
5
6
7
8
# 编写脚本,查看当前的网络状态。当ping命令可以ping通时,即显示对应的网络状态is up, 否则为down.
# 脚本内容如下:
#!/bin/bash
ping -c1 -w1 $1 && {
echo $1 is up
} || {
echo $1 is down
}
2.5 sort

多用于字符排序

1
2
3
4
5
6
7
8
9
10
11
12
[root@mxsenn ~]$ sort [选项] [file or stdin]
选项与参数:
-f :忽略大小写的差异,例如 A 与 a 视为编码相同;
-b :忽略最前面的空白字符部分;
-M :以月份的名字来排序,例如 JAN,DEC 等等的排序方法;
-n :使用“纯数字”进行排序(默认是以文字体态来排序的);
-r :反向排序;
-u :就是 uniq,相同的数据中,仅出现一行代表;
-t :分隔符号,默认是用 [tab] 键来分隔;
-k :以那个区间 (field) 来进行排序的意思
[root@mxsenn ~]# sort -nt ":" -k 3 /mnt/passwd
以数字排序方式,以“:”为分隔符,对 /etc/passwd 的第三列内容进行排序
2.6 uniq

对重复的字符作出相应处理,一般与排序连用

1
2
3
4
[root@mxsenn ~]# uniq 
-u 显示唯一的以行
-d 显示重复的行
-c 每行显示一次并统计重复次数
2.7 test

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

test 命令和 [ ] 等同
[ “a” == “b”] 等同于 test a = b

A 判定字符串的数据

判定方式 含义
test -z string 判定字串长度是否为 0 若 string 为空字串,则为 true
test -n string 判定字串长度是否非 0 若 string 为空字串,则为 false -n 亦可省略
test str1 == str2 判定 str1 是否等于 str2 ,若相等,则回传 true
test str1 != str2 判定 str1 是否不等于 str2 ,若相等,则回传 false

B 多重条件判定,例如: test -r filename -a -x filename

判定方式 含义
-a (and)两状况同时成立!例如 test -r file -a -x file则 file 同时具有 r 与 x 权限时,才回传 true
-o (or)两状况任何一个成立!例如 test -r file -o -x file,则 file 具有 r 或 x 权限时,就可回传 true

C 关于两个整数之间的判定,例如 test n1 -eq n2

判定方式 含义
-eq 两数值相等 (equal)
-ne 两数值不等 (not equal)
-gt n1 大于 n2 (greater than)
-lt n1 小于 n2 (less than)
-ge n1 大于等于 n2 (greater than or equal)
-le n1 小于等于 n2 (less than or equal)

D 两个文件之间的比较,如:test file1 -nt file2

判定方式 含义
-nt (newer than)判断 file1 是否比 file2 新
-ot (older than)判断 file1 是否比 file2 旧
-ef 判断 file1 与 file2 是否为同一文件,可用在判断hard link(硬链接) 的判定上。主要意义在判定,两个文件是否均指向同一个 inode

E 关于某个文件名的“文件类型”判断,如 test -e filename 表示存在否

判定方式 含义
-e 该“文件名”是否存在
-f 该“文件名”是否存在且为文件(file)
-d 该“文件名”是否存在且为目录(directory)
-b 该“文件名”是否存在且为一个 块设备(block device) 设备
-c 该“文件名”是否存在且为一个 字符串(character device) 设备
-S 该“文件名”是否存在且为一个 套接子(Socket) 文件
-L 该“文件名”是否存在且为一个 链接(软链接)文件
2.8 tr

tr 可以用来删除一段讯息当中的文字,或者是进行文字讯息的替换

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
示例一:将 w 输出的讯息中,所有的小写变成大写字符:
[root@mxsenn ~]# w | tr 'a-z' 'A-Z'

示例二:
编写脚本将输入的单词与 HELLO 进行比较,若为 小写字符的 hello 将输出 yes 否则输出no
其中若输入的为大写字符,将大写字符转化为小写字符

#!/bin/bash
WORD=`echo $1`
if [ "$WORD" = "hello" ]; then #将输入的单词与 hello 比较
echo yes #若相同,输出 yes
elif [ "$WORD" = 'HELLO' ]; then #将输入的单词与 HELLO 比较
echo no #若相同,输出no
echo $WORD | tr 'A-Z' 'a-z' #将大写转换为小写后输出
else
echo no
fi
2.9 $相关
命令 含义
$$ shell本身的PID
$! shell最后运行的后台PID
$? 最后运行的命令返回的结束代码(0表示正常,其他表示异常)
$* 传给shell脚本的所有参数的列表,若$*用”括起来,以”$1 $2 … $n”形式输出所有参数
$@ 传给shell脚本的所有参数的列表,若$@用”括起来,以”$1” “$2” … “$n”形式输出所有参数
$# 传给shell脚本的参数个数
$0 shell脚本本身的文件名
$1 ~ $n 传给shell脚本的各个参数值,如$1表示第一个参数
坚持原创技术分享,您的支持将鼓励我继续创作!

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