Shell的前世今生
现在的操作系统(Windows、Mac OS、Android、iOS等)都是带图形界面的,简单直观,容易上手,可以说老少皆宜。 然而在计算机的早期发展时期却并没有图形化的界面,我们只能通过一个一个地命令来控制计算机,成堆的命令记住都非常困难,更别说熟练使用了,这个时候的计算机的使用门槛非常的高,只有专业的人员才能进行使用。 为了让计算机能够更好的普及下去,开发人员做了非常多的努力,他们发现:对于图形化的界面来说,用户点击某一个图标就能启动某个程序和使用命令行来启动程序在本质上都是类似的,都是查找程序在硬盘的安装位置,然后将他们加载到内存中运行。然而,真正能够控制计算机硬件(CPU,内存等)的只有操作系统的内核Kernel,无论是图形化的界面还是命令行都只是为了用户和内核之间建立一座沟通的桥梁。由于安全、复杂、繁琐等原因,用户不能直接接触内核(也没有必要),需要另外再开发一个程序,让用户直接使用这个程序;该程序的作用就是接收用户的操作(点击图标、输入命令),并进行简单的处理,然后再传递给内核。如此一来,用户和内核之间就多了一层“代理”,这层“代理”既简化了用户的操作,也保护了内核。
用户界面和命令行就是这个另外开发的程序,就是这层“代理”。在Linux下,这个命令行程序叫做 Shell。
Shell的种类
Linux 中提供的Shell解析器有如下几种:
bash 和 sh 的区别:
sh 的全称是 Bourne shell,由 AT&T 公司的 Steve Bourne开发,为了纪念他,就用他的名字命名了。
sh 是 UNIX 上的标准 shell,很多 UNIX 版本都配有 sh。
sh 是第一个流行的 Shell。
bash shell 是 Linux 的默认 shell,bash 由 GNU 组织开发,保持了对 sh shell 的兼容性,是各种 Linux 发行版默认配置的 shell。bash 兼容 sh 意味着,针对 sh 编写的 Shell 代码可以不加修改地在 bash 中运行。
简单的Shell脚本
用Shell编写一个helloworld.sh:
2. 多命令处理Shell脚本:
Shell中的变量
1. 常见系统变量:
2. 自定义变量:
定义变量:变量=值(=号两侧不能有空格)
撤销变量:unset变量
声明静态变量:readonly变量(不能撤销)
注意事项:
1. 变量名称可以用字母、数字、下划线组成,不能用数字开头。
2. 变量默认类型都是字符串类型,无法直接进行数值上的计算。
3. 变量的值中如果包含有空格,则需要使用双引号括起来。
3. 常见特殊变量 :
$n: $n中的n是数字,($0代表脚本名称,$1-9代表第1-9个参数,10个参数以上需要用大括号,比如说${10})
$# :获取所有输入参数个数,常用于循环
$* : 获取命令行中所有的参数(看成一个整体)
$@: 获取命令行中所有的参数(区别对待)
$? : 获取最后一次执行的命令的返回状态(0表示正确执行,不是则未能正确执行)
Shell中运算符
两种语法方式:
$[运算式]
expr +, - , \*, / , % (运算符之间要有空格)
条件判断
[ condition ] : 注意condition前后要有空格常见的判断条件:1. 字符串类型 :
= 字符串比较
-lt 小于(less than)
-le 小于等于 (less equal)
-eq 等于(equal)
-gt 大于(greater than)
-ge 大于等于
-ne 不等于(not equal)
2. 文件权限:
-r/w/x 是否有读/写/执行的权限
3. 文件类型
-f 文件是不是一个常规的文件 (file)
-e 文件是否存在 (existence)
-d 文件是否是一个目录(directory)
流程控制
if 语句:
if [ condition ] 代码逻辑elif [ condition ]then 代码逻辑 fi (代表结束)
case语句:
case $变量名 in"值1") 如果变量的值等于值1,则执行该段逻辑;;"值2") 如果变量的值等于值2,则执行该段逻辑;;"*") 如果变量的值和上面的都不相等,则执行该段逻辑;;esac
for语句:
for (( 初始值;循环控制条件;变量变化 )) do 代码逻辑 done
for 变量 in 值1 值2 值3… do 代码逻辑 done
ps : $* 表示传递给脚本的所有参数
while语句:
while [ 条件判断式 ] do 程序代码 done
read 语句:(从键盘读取信息)
-t : 指定读取值时等待的时间(秒)
-p:指定读取值时的提示符;
函数
系统函数:
basename: 删除所有的前缀包括 / ,将字符串显示出来
dirname: +文件绝对路径(从给定的包含绝对路径的文件名中取出非目录的部分),返回目录部分
自定义函数:
[ function ] name(){ 函数逻辑}
Shell工具(重点)
cut:从文件中剪切数据的工具
cut + 选项参数 + filename选项参数:-f : 按照列号截取-d : 按照指定的分隔符截取
sed : 流编辑器,处理时,把当前处理的行存储在临时缓冲区中,称为“模式空间”,接着用sed命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕。接着处理下一行,这样不断重复,直到文件末尾。文件内容并没有改变,除非你使用重定向存储输出。
sed + 选项参数 + ‘命令参数’ + filename选项参数 : -e : 直接在指令列模式上进行sed的动作编辑命令参数: a : 新增,a的后面可以接字符串,在下一行出现 d : 删除 s : 查找并替换
awk : 一个文本分析工具,把文件逐行读入,以空格为默认分隔符将每行切片,切开的部分再进行相应的分析处理
awk + 选项参数 + ‘ 匹配模式1{命令1} 匹配模式2{命令2} ’ filename选项参数 :-F :按照指定分隔符分隔(类似于cut中的-d)
需求1 : 搜索文件找到root开头的所有行,并输出第7列
需求2 : 搜索文件找到root开头的所有行,并输出第2列和第5列,用,分隔。
需求3 : 在第一行前面加上user,binshow。在最后一行添加"ustc, /bin/binshow",只显示第一列和第7列
awk的内置变量:FILENAME :文件名NR :已读的记录数NF : 浏览记录的域的个数(切割后列的个数)
sort : 将文件排序,并将排序结果标准化输出
sort + 选项 + 待排序的文件列表选项:-n 按照数值的大小排序-r 以相反的顺序来排序-t 设置排序时所用的分隔字符-k 指定需要排序的列
部分面试题
如何在脚本中使用参数 ?
如何检查之前的命令是否运行成功?
假如文件中每行第一个元素是FIND,如何获取第二个元素?
如何使用 awk 列出 UID 小于 100 的用户 ?
shell 脚本如何获取输入的值 ?
1. 第一个参数 : $1,第二个参数 :$22. $?3. awk'{ if ($1 == "FIND") print$2}'4. awk -F: '$3<100' /etc/passwd5. read -p "input your num :" num
该部分学习建议 :
知识繁杂,多敲几遍。只需要记住一些常见的命令即可,后续工作中遇到再去查阅,不需要死记硬背。适用于校招准备时间较长的同学,时间很短的话本部分内容不是重点。