Shell编程、part1
1.shell简介
2. shell分类
3. 查看shell
4. 第一个shell脚本
5. shell编程常用命令
5.1 grep
5.2 cut
5.3 sort
5.4 uniq
5.5 seq
5.6 tr
前言
什么是脚本?
脚本简单地说就是一条条的文字命令(一些指令的堆积),这些文字命令是可以看到的(如可以用记事本打开查看、编辑)。
常见的脚本: JavaScript(J****S****,前端),VBScript, ASP,JSP,PHP(后端),SQL(数据库操作语言),Perl,Shell,python,Ruby,JavaFX, Lua等。
为什么要学习和使用shell?
Shell属于内置的脚本程序开发的效率非常高,依赖于功能强大的命令可以迅速地完成开发任务(批处理)
语法简单,代码写起来比较轻松,简单易学
1.1 Shell 简介
Shell 是一个 C 语言编写的脚本语言,它是用户与 Linux 的桥梁,用户输入命令交给 Shell 处理, Shell 将相应的操作传递给内核(Kernel),内核把处理的结果输出给用户。
下面是流程示意图:
imageShell 既然是工作在 Linux 内核之上,那我们也有必要了解下 Linux 相关知识。 Linux 是一套免费试用和自由传播的类 Unix 操作系统,是一个基于 POSIX 和 UNIX 的多用户、多任 务、支持多线程和多 CPU 的操作系统。
1983 年 9 月 27 日,Richard Stallman(理查德-马修-斯托曼)发起 GNU 计划,它的目标是创建一 套完全自由的操作系统。为保证 GNU 软件可以自由的使用、复制、修改和发布,所有的 GNU 软件都 有一份在禁止其他人添加任何限制的情况下授权所有权利给任何人的协议条款,GNU 通用公共许可 证(GNU General Plubic License,GPL),说白了就是不能做商业用途。
GNU 是”GNU is Not Unix”的递归缩写。UNIX 是一种广泛使用的商业操作系统的名称。
1985 年,Richard Stallman 又创立了自由软件基金会(Free Software Foundation,FSF)来为 GNU 计划提供技术、法律以及财政支持。
1990 年,GNU 计划开发主要项目有 Emacs(文本编辑器)、GCC(GNU Compiler Collection,GNU 编 译器集合)、Bash 等,GCC 是一套 GNU 开发的编程语言编译器。还有开发一些 UNIX 系统的程序库和 工具。
1991 年,Linuxs Torvalds(林纳斯- 托瓦兹)开发出了与 UNIX 兼容的 Linux 操作系统内核并在 GPL 条款下发布。
1992 年,Linux 与其他 GUN 软件结合,完全自由的 GUN/Linux 操作系统正式诞生,简称 Linux。
1995 年 1 月,Bob Young 创办 ACC 公司,以 GNU/Linux 为核心,开发出了 RedHat Linux 商业版。
Linux 基本思想有两点:第一,一切都是文件;第二,每个软件都有确定的用途。
与 Unix 思想十分 相近。 Kernel Shell 命令 用户 解析命令 并传递给内核 执行动作
source filename 与 bash filename 及./filename执行脚本的区别
-
当shell脚本具有可执行权限时,用bash filename与./filename执行脚本是没有区别得。./filename是因为当前目录没有在PATH中,所以”.”是用来表示当前目录的。
-
source filename:这个命令其实只是简单地读取脚本里面的语句依次在当前shell里面执行,没有建立新的子shell。那么脚本里面所有新建、改变变量的语句都会保存在当前shell里面。
-
bash filename 重新建立一个子shell,在子shell中执行脚本里面的语句,该子shell继承父shell的环境变量,但子shell新建的、改变的变量不会被带回父shell。
最后一句话什么意思那?
子shell新建变量,在父shell中不会生效:
我们可以使用命令pstree查看我们当前所处的位置
需要下载
[root@ken ~]# yum search pstree
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile ==================================================== Matched: pstree ==================================================== psmisc.x86_64 : Utilities for managing processes on your system
texlive-pst-tree.noarch : Trees, using pstricks
[root@ken ~]# yum install psmisc -y
使用pstree
我们再次执行bash,就会进入到另外一个子shell中
这个时候我们在这个子shell中定义一个变量,发现可以正确打印出来
[root@ken ~]# age=25 [root@ken ~]# echo $age 25</pre>
现在我们退出当前的shell,即进入了当前子shell中的父shell中,再次打印我们刚才定义的变量可以发现现在已经无法获取到我们刚才定义的变量值了。
子shell继承父shell的环境变量:
我们把环境变量定义到profile的一个子文件中,并使用source执行该文件并生效,打开一个子shell,定义在父shell中的环境变量依然有效,反之,这种操作在子shell中操作,父shell也不能继承。
[root@ken ~]# cat /etc/profile.d/ken.sh
export name=ken
[root@ken ~]# source /etc/profile.d/ken.sh
[root@ken ~]# echo $name
ken
[root@ken ~]# bash
[root@ken ~]# echo $name
ken
shell脚本命名
1.见名知意
- 结尾.sh
shell脚本编写
#!/bin/bash #声明shell解释器
echo “Hello World” #执行的command
shell脚本的运行
第一种方式:bash
[root@ken ~]# bash hello_w.sh
Hello World
第二种方式:路径方式 #要给脚本添加执行权限
[root@ken ~]# ./hello_w.sh
-bash: ./hello_w.sh: Permission denied
[root@ken ~]# ./hello_w.sh
-bash: ./hello_w.sh: Permission denied
[root@ken ~]# ll
total 102412
-rw——-. 1 root root 1206 Feb 26 22:25 anaconda-ks.cfg
-rw-r–r– 1 root root 0 Mar 11 19:08 a.out
-rw-r–r– 1 root root 31 May 29 09:55 hello_w.sh
drwxr-xr-x 3 root root 80 Mar 11 18:18 ken1
lrwxrwxrwx 1 root root 4 Mar 12 11:06 test1 -> test
-rw-r–r– 1 root root 4 Mar 12 11:09 test2
-rw-r–r– 1 root root 104857600 Mar 12 18:03 test.txt
[root@ken ~]# chmod +x hello_w.sh
[root@ken ~]# ll
total 102412
-rw——-. 1 root root 1206 Feb 26 22:25 anaconda-ks.cfg
-rw-r–r– 1 root root 0 Mar 11 19:08 a.out
-rwxr-xr-x 1 root root 31 May 29 09:55 hello_w.sh
drwxr-xr-x 3 root root 80 Mar 11 18:18 ken1
lrwxrwxrwx 1 root root 4 Mar 12 11:06 test1 -> test
-rw-r–r– 1 root root 4 Mar 12 11:09 test2
-rw-r–r– 1 root root 104857600 Mar 12 18:03 test.txt
[root@ken ~]# ./hello_w.sh
Hello World
第三步:方式
[root@ken ~]# source hello_w.sh
Hello World
[root@ken ~]# chmod -x hello_w.sh
[root@ken ~]# source hello_w.sh
Hello World
练习1:使用root用户帐号创建并执行test2.sh,实现创建一个shelltest用户,并在其家目录中新建文件try.html。
[root@ken ~]# cat test2.sh
#!/bin/bash
useradd shelltest
touch /home/shelltest/try.html
执行结果:
[root@ken ~]# id shelltest
uid=1001(shelltest) gid=1001(shelltest) groups=1001(shelltest)
[root@ken ~]# ls /home/shelltest/
try.html
练习2:统计当前系统总共有多少用户
[root@ken ~]# cat test3.sh
#!/bin/bash
wc -l /etc/passwd
执行结果:
[root@ken ~]# bash test3.sh
22 /etc/passwd
练习3:统计当前已经安装的软件数量
[root@ken ~]# cat test4.sh
#!/bin/bash
yum list installed | wc -l
执行结果:
[root@ken ~]# bash test4.sh
353
shell脚本常用命令
1.grep: 过滤文本文件内容
常用选项:
选项 描述
-E,–extended-regexp 模式是扩展正则表达式(ERE)
-i,–ignore-case 忽略大小写
-n,–line-number 打印行号
-o,–only-matching 只打印匹配的内容
-c,–count 只打印每个文件匹配的行数
-B,–before-context=NUM 打印匹配的前几行
-A,–after-context=NUM 打印匹配的后几行
-C,–context=NUM 打印匹配的前后几行
–color[=WHEN], 匹配的字体颜色
-v,–invert-match 打印不匹配的行
样本文件内容
[root@ken ~]# cat test
dlakdlad
ad
ad
a
dFSAF
A
F
F
AS
F
f
sf
as
f
实例1:打印出所有的a无论大小写 : -i选项
[root@ken ~]# grep -i “a” test
dlakdlad
ad
ad
a
dFSAF
A
AS
as
实例2:打印出所有的a无论大小写,并且显示该字符串所在的行 : -n选项
[root@ken ~]# grep -i -n “a” test
1:dlakdlad
2:ad
3:ad
4:a
5:dFSAF
6:A
9:AS
13:as
实例3:仅仅打印出所有匹配的字符串: -o选项
[root@ken ~]# grep -i -o “a” test
a
a
a
a
a
A
A
A
a
实例4:打印出匹配的字符串有多少行 -c选项
[root@ken ~]# grep -i -c “a” test
8
实例5:打印出字符S前面的2行 -B
[root@ken ~]# grep -B 2 “S” test
ad
a
dFSAF
—
F
F
AS
实例6:打印出字符S后面的2行 -A
[root@ken ~]# grep -A 2 “S” test
dFSAF
A
F
—
AS
F
f
实例7:打印出字符S后面的2行 -C
[root@ken ~]# grep -C 2 “S” test
ad
a
dFSAF
A
F
F
AS
F
f
实例8:打印出不包含大小s的所有行 取反 -v
[root@ken ~]# grep -i -v “s” test
dlakdlad
ad
ad
a
A
F
F
F
f
f
grep可以从文件当中直接搜索某个关键词,也可以从标准输入里面搜错
[root@ken ~]# grep root /etc/passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
[root@ken ~]# cat /etc/passwd | grep “root”
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
2.cut
-c :以字符为单位进行分割。
-d :自定义分隔符。
-f :与-d一起使用,指定显示哪个区域。
实例1:获取6位随机加密数
[root@ken ~]# echo $RANDOM | md5sum | cut -c 1-6
bb2788
[root@ken ~]# echo $RANDOM | md5sum | cut -c 1-6
45a0e0
实例2:截取指定的字符串
[root@ken ~]# echo “abcd” | cut -c 2
b
实例3:截取出来/etc/passwd用户名
[root@ken ~]# cat /etc/passwd | cut -d “:” -f 1
root
bin
daemon
adm
lp
sync
shutdown
halt
实例4:截取出来/etc/passwd用户的shell类型
[root@ken ~]# cat /etc/passwd | cut -d “:” -f 7
/bin/bash
/sbin/nologin
/sbin/nologin
/sbin/nologin
/sbin/nologin
/bin/sync
/sbin/shutdown
实例5:截取出来/etc/passwd用户以及shell类型
[root@ken ~]# cat /etc/passwd | cut -d “:” -f 1,7
root:/bin/bash
bin:/sbin/nologin
daemon:/sbin/nologin
adm:/sbin/nologin
lp:/sbin/nologin
sync:/bin/sync
shutdown:/sbin/shutdown
halt:/sbin/halt
3.sort
-k:根据切割后的那一段进行排序
-n 依照数值的大小排序(默认是根据字符进行排序)。
-r 以相反的顺序来排序。
-t<分隔字符> 指定排序时所用的栏位分隔字符。
-u:去除重复的行(只要那个指定的字段重复,就认定是重复的行)
演示文件
[root@ken ~]# cat test
12
23
2
3
5
实例1:以数字排序 -n
[root@ken ~]# sort test
12
2
23
3
5
[root@ken ~]# sort -n test
2
3
5
12
23
实例2:降序排序
[root@ken ~]# sort -n -r test
23
12
5
3
2
实例3:降序排序并取出前3行
[root@ken ~]# sort -n -r test | head -3
23
12
5
演示文件
[root@ken ~]# cat test
12:3
23:4
2:12
3:5
5:23
实例4:以冒号为分隔符,第二列进行数字降序排序
[root@ken ~]# cat test | sort -t “:” -k2 -n -r
5:23
2:12
3:5
23:4
12:3
演示文本:
[root@ken ~]# cat test
12:3
12:3
12:3
12:3
23:4
2:12
3:5
3:5
3:5
3:5
5:23
实例5:显示行并去除重复行
[root@ken ~]# sort -u test
12:3
2:12
23:4
3:5
5:23
- uniq
-c:在行首用数字表示该行出现了多少次
-u:仅仅显示那些没有出现重复过的行
演示文件
[root@ken ~]# cat test
12:3
12:3
12:3
12:3
23:4
2:12
3:5
3:5
3:5
3:5
5:23
实例1:统计每行出现的次数
[root@ken ~]# uniq -c test
4 12:3
1 23:4
1 2:12
4 3:5
1 5:23
实例2:演示没有出现出重复行的数量
[root@ken ~]# uniq -u test
23:4
2:12
5:23
5,seq
实例1:
[root@ken ~]# seq 5
1
2
3
4
5
实例2:
[root@ken ~]# seq 2 5
2
3
4
5
实例3:
[root@ken ~]# seq 2 2 10 #第一个2是起始位,第二个2是步长,第三个10是终止位
2
4
6
8
10
实例4:取出100以内所有的奇数
[root@ken ~]# seq 1 2 100
1
3
5
7
9
11
13
15
17
实例5:取出100以内所有的偶数
[root@ken ~]# seq 2 2 100
2
4
6
8
10
12
14
16
6.tr命令:命令用于转换或删除文件中的字符
-d:删除指定的字符串
实例1:把所有的小写字母都转化为大写字母
[root@ken ~]# echo “daadadfaedqdac” | tr a-z A-Z
DAADADFAEDQDAC
实例2:把所有的大写字母都转化为小写字母
[root@ken ~]# echo “SDSDA2WZFAF” | tr A-Z a-z
sdsda2wzfaf
实例3:删除一行中的空格
[root@ken ~]# echo “ada dada dada” | tr -d ” ”
adadadadada