问题导读
1.Shell该如何学习?
2.Shell和传统编程语言有哪些相同之处?
3.Shell和传统编程语言有哪些不同之处?
4.你认为Shell还有哪些便捷的地方?
由于行业的发展,对程序员的要求越来越高,原先我们只会一门语言就可以找到工作,现在我们需要会的东西越来越多,会一门语言只是入门开发而已,目前你会大数据更好,会算法、机器学习那已经成为佼佼者。所以我们这个行业需要不断的学习、成长和进步。
这里我们所说的Shell,其实无论是大数据、云技术、还是其它等,其实很多都可以用到。但是作为传统开发程序员来讲,对它可能还是停留在简单的使用阶段。比如根据文档可以安装部署大数据组件,比如Hadoop、Spark等。但是这距离我们使用Shell编程,还是有一定距离的。
本文主要针对零基础、面试Shell不知道该如何补充这方面的知识,以及工作中想学习Shell的老铁。
零基础Shell
对于零基础的老铁,其实只要经常使用Linux即可熟悉基本的Linux操作。例如复制文件cp、移除文件mv、创建文件夹mkdir、编辑文件vi、查看文件cat、授权chmod、chown等,当然比如网络配置、开机、关机等这些也是在我们安装部署集群所必备的。对于这些常用的命令或则shell,我们只要多安装集群,会变的比较熟悉。
更多可参考
解决遇到Linux网络配置,从熟悉网络配置文件入手
linux入门大全:包括零基础入门,Linux详细介绍
Linux重启方式init 0 init1 init 3 init 5 init 6 这几个启动级别都代表什么意思?
Ubuntu常用命令总结及修改DNS的多种方法总结
Linux关机各种关机命令总结
Linux基础必懂:eth0,eth1,eth2,lo是什么意思?
linux中pwd命令详解
linux之vi编辑器
linux yum命令详解
Linux下chkconfig命令详解
Shell编程
Shell编程,这里对很多人来说就有点难度了,如果我们掌握了Shell编程,会让我们在职场中更有优势,面试亦是亮点。一些企业包括很多的名企,招聘中都提到了Shell。
我们可以看到无论是Java高级工程师,还是大数据工程师,都要求会使用Shell。那么我们该如何补充这方面的知识。
Shell与传统编程语言比较
1.相同点
Shell已经被视为一种编程语言,既然是编程,那么它和其它编程语言有什么相同之处?
我们在学习Shell的时候,大多都是觉得Shell是比较难学的,其实如果我们确实深入了解下,它和我们的其它编程语言,有太多的相似之处。
在编程中,流程控制,我们知道条件判断if else,case ,循环比如for,while等是基本的编程结构,那么在Shell中其实也是同样存在的,数组、函数在shell亦是存在的,当然在实现细节方面略有不同。
比如shell中的if else,如下面格式
[mw_shl_code=bash,true]if condition
then
command1
command2
...
commandN
else
command
fi[/mw_shl_code]
我们可以看到其实就两点区别:多了两个单词,一个then,以及以fi结尾。这样我们就掌握了shell中if else的用法,看是非常简单的。
对于shell编程更多内容可参考
Shell 变量
Shell 传递参数
Shell 数组
Shell 基本运算符
Shell echo命令
Shell printf 命令
Shell 流程控制
Shell 函数
Shell 输入/输出重定向
Shell 文件包含
2.不同点
Shell既然为Shell,那么和其它编程语言也有不同的地方。比如管道符。
管道符
管道符我们或许听说过或则没有听说过,但是我们会被它的名字所迷惑,管道符到底是什么?它的作用是什么?当然我们看到下面例子的时候,一看就会变的非常简单。
这里举例比如我们遇到问题,想查看Linux进程
ps -aux | grep *** 查询***进程的详细信息;
对于上面|即为管道符。那么为什么称之为管道符?
原因为:管道符是将第一个命令的结果传递给第二个命令作为输入。这是不是比较神奇,而且作用非常大。
比如我们上面命令查看进程,进程的结果进一步过滤,我们通过管道符+grep实现了对结果的进一步过滤。
在比如:
把原本要输出到屏幕的用户信息列表再交给 wc 命令作进一步的加工
[mw_shl_code=bash,true]grep "/sbin/nologin" /etc/passwd | wc -l[/mw_shl_code]
比如用翻页的形
式查看/etc 目录中的文件列表及属性信息(这些内容默认会一股脑儿地显示到屏幕上,根本看不清楚):
[mw_shl_code=bash,true][root@linuxprobe ~]# ls -l /etc/ | more
total 1400
drwxr-xr-x. 3 root root 97 Jul 10 17:26 abrt
-rw-r--r--. 1 root root 16 Jul 10 17:36 adjtime
-rw-r--r--. 1 root root 1518 Jun 7 2013 aliases
-rw-r--r--. 1 root root 12288 Jul 10 09:38 aliases.db
drwxr-xr-x. 2 root root 49 Jul 10 17:26 alsa
drwxr-xr-x. 2 root root 4096 Jul 10 17:31 alternatives
-rw-------. 1 root root 541 Jan 28 2017 anacrontab
-rw-r--r--. 1 root root 55 Jan 29 2017 asound.conf
-rw-r--r--. 1 root root 1 Jan 29 2017 at.deny
drwxr-xr-x. 2 root root 31 Jul 10 17:27 at-spi2
drwxr-x---. 3 root root 41 Jul 10 17:26 audisp
drwxr-x---. 3 root root 79 Jul 10 17:37 audit
drwxr-xr-x. 4 root root 94 Jul 10 17:26 avahi
--More--[/mw_shl_code]
除了管道符,还有两个非常重要的工具,这两个的使用,直接影响了别人认为我们是否熟悉shell的一个标识。一个是sed,一个是awk。
既然这两个这么重要,那么我们来认识下这两个工具。
sed使用
什么情况下使用sed,比如我们想偷懒,不想打开文件然后在各种操作,那么这时候我们就可以使用sed了。
sed可以完成的操作很多,比如sed截取文件
[mw_shl_code=bash,true]sed -n ‘1,6p’ filename >newfilename
[/mw_shl_code]
使用sed加“-n”参数来完成对文件某几行的截取,上述sed命令就可以截取文件中的1到6行然后输出到新文件中。
sed替换文件内字符
[mw_shl_code=bash,true]sed -i ‘s/old/new/’filename
[/mw_shl_code]
还有其他功能比如删除文件的某些特征行,某些变量前添加内容。关于sed使用更多可参考
Linux sed工具命令详解
https://www.aboutyun.com/forum.php?mod=viewthread&tid=28389
awk使用
awk跟sed差不多,也可以操作文件。而且说它是一门编程语言也不为过。
我们来看它的简单的使用。在举例之前,需要说下,shell中有默认的变量,比如一个文件如下:
a b c
a1 b1 c1
a2 b2 c2
如果我们使用语言api,该如何获取第一列数据,相信这个不同的语言实现有所不同,可是awk那太简单了,只需要一个变量即可实现,$1:表示第一列,$2表示第二列,$3表示第三列。对滴这就是Shell的便捷之处,我们可能使用大量的语言编程,在shell中可能一行代码就可以搞定了。我们接着来看。
比如我们查看某个目录的文件:
[mw_shl_code=bash,true] ls -lh
[/mw_shl_code]
[mw_shl_code=bash,true]total 136K
-rwxr-xr-x 1 root root 766 Jul 22 2011 colorls.csh
-rwxr-xr-x 1 root root 727 Jul 22 2011 colorls.sh
-rw-r--r-- 1 root root 92 Feb 23 2012 cvs.csh
-rwxr-xr-x 1 root root 78 Feb 23 2012 cvs.sh
-rwxr-xr-x 1 root root 192 Mar 25 2009 glib2.csh
-rwxr-xr-x 1 root root 192 Mar 25 2009 glib2.sh
-rw-r--r-- 1 root root 218 Jun 6 2013 krb5-devel.csh
-rw-r--r-- 1 root root 229 Jun 6 2013 krb5-devel.sh
-rw-r--r-- 1 root root 218 Jun 6 2013 krb5-workstation.csh
-rw-r--r-- 1 root root 229 Jun 6 2013 krb5-workstation.sh
-rwxr-xr-x 1 root root 3.0K Feb 22 2012 lang.csh
-rwxr-xr-x 1 root root 3.4K Feb 22 2012 lang.sh
-rwxr-xr-x 1 root root 122 Feb 23 2012 less.csh
-rwxr-xr-x 1 root root 108 Feb 23 2012 less.sh
-rwxr-xr-x 1 root root 97 Mar 6 2011 vim.csh
-rwxr-xr-x 1 root root 293 Mar 6 2011 vim.sh
-rwxr-xr-x 1 root root 170 Jan 7 2007 which-2.sh[/mw_shl_code]
awk的使用,例如只打印第一列:
[root@localhost profile.d]# ls -lh | awk '{print NR " " $1}'
1 total
2 -rwxr-xr-x
3 -rwxr-xr-x
4 -rw-r--r--
5 -rwxr-xr-x
6 -rwxr-xr-x
7 -rwxr-xr-x
8 -rw-r--r--
9 -rw-r--r--
10 -rw-r--r--
11 -rw-r--r--
12 -rwxr-xr-x
13 -rwxr-xr-x
14 -rwxr-xr-x
15 -rwxr-xr-x
16 -rwxr-xr-x
17 -rwxr-xr-x
18 -rwxr-xr-x
上面我看到awk确实使用起来非常方便,而且如果我们稍微学习下,其实也不难的,更多awk可参考
https://www.aboutyun.com/home.php?mod=space&uid=61&do=blog&id=4338
3.Shell便捷之处
有了传统编程语言,为何会有shell编程。让我们来看看做同样的事情,Shell到底有多便捷。
我们就以数据清洗为例:
如果我们使用语言API,那么首先我们需要有开发环境,比如IDEA,Eclipse等,这个如果你不熟悉就够麻烦的了。有了环境之后,我们还需要会使用语言API,API编程,我们知道要有类,有入口函数Main以及功能实现等。
我们就以日志清洗,我们可以看到通过api的实现。
[mw_shl_code=scala,true]import org.apache.spark.SparkConf
import org.apache.spark.storage.StorageLevel
import org.apache.spark.streaming.{Seconds, StreamingContext}
import scala.util.matching.Regex
/**
* Created by PeersLee on 2017/2/8.
*/
object ExtractFromLocal {
def main(args: Array[String]): Unit = {
//创建SparkConf,设置AppName和Master
// var:声明变量,val:声明常量
val conf = new SparkConf().setAppName("ExtractFromLocal").setMaster("local")
// 创建一个具有n个线程10秒间隔时间的本地StreamingContext
val ssc = new StreamingContext(conf, Seconds(10))
// 上面我们已经创建一个DStream(连续的数据流),这个ssc可以从TCP源(ip : localhost, port : 9999) 获取流数据,
// 开始获取数据
val hostname = "192.168.1.10"
val port = 9999
val lines = ssc.socketTextStream(hostname, port, StorageLevel.MEMORY_AND_DISK_SER)
// 处理逻辑
。。。。。
words.print()
//开始执行,并在控制台等待
ssc.start()
ssc.awaitTermination()
}
}
[/mw_shl_code]
更多可参考:
about云日志分析项目准备10-3:Spark Local模式之Log文本清洗
https://www.aboutyun.com/forum.php?mod=viewthread&tid=21135
上面我们先不管逻辑,就可以看到需要大量的代码,那么用Shell,该如何实现:
下面一行代码即可实现
[mw_shl_code=bash,true]awk '($7 !~ /^\/static\//){print $0}' access_2013_05_30.log > clean_2013_05_30.log
[/mw_shl_code]
解释:
清洗去除URL中以/static/开头的URL
上面我们看到Shell是非常简练的。
Shell面试题
面试题,其实只要我们打好基础,面试题难不倒我们的。特别是我们所讲的sed和awk的使用。有些老铁为了面试只是背面试题,而不去往基础和知识的源头去学习,那只能是会了这个,忘了那个。所以即使我们针对面试,我们亦应该针对经常出现的面试题,去总结经常被问的知识点,如果这些知识点熟悉了,那么对于它所对应的所有问题,也就迎刃而解了。下面是关于Shell的面试题,如果上面我们知识点都熟悉了,你会发现下面的面试题不在困难。
一、取出/etc/passwd文件中shell出现的次数
问题:
下面是一个/etc/passwd文件的部分内容。题目要求取出shell并统计次数,shell是指后面的/bin/bash,/sbin/nologin等,如下面/bin/bash出现12次,/sbin/nologin出现3次。
hyn:x:525:500::/home/hyn:/bin/bash ljlxx:x:526:500::/home/ljlxx:/bin/bash lzj:x:527:500::/home/lzj:/bin/bash wfly:x:528:500::/home/wfly:/bin/bash squid:x:23:23::/var/spool/squid:/sbin/nologin wyj:x:529:500::/home/wyj:/bin/bash qemu:x:107:107:qemu user:/:/sbin/nologin radvd:x:75:75:radvd user:/:/sbin/nologin dungbee:x:530:500::/home/dungbee:/bin/bash mysql:x:27:27:MySQL Server:/var/lib/mysql:/bin/bash scidb:x:531:531::/home/scidb:/bin/bash postgres:x:532:532::/home/postgres:/bin/bash crane:x:533:533::/home/crane:/bin/bash test:x:534:534::/home/test:/bin/bash hguser:x:535:535::/home/hguser:/bin/bash
参考答案:
cat /etc/passwd|awk -F: '{print $7}'|sort|uniq -c
解析:
使用awk根据冒号分割内容,打印输出分割后的第7列,也就是shell所在列。然后调用sort命令排序并使用uniq -c统计每个shell出现的次数。
二、文件整理
问题:
employee文件中记录了工号和姓名
employee.txt: 100 Jason Smith 200 John Doe 300 Sanjay Gupta 400 Ashok Sharma
bonus文件中记录工号和工资
bonus.txt: 100 $5,000 200 $500 300 $3,000 400 $1,250
要求把两个文件合并并输出如下
处理结果:
400 ashok sharma $1,250 100 jason smith $5,000 200 john doe $500 300 sanjay gupta $3,000
参考答案:
paste employee.txt bonus.txt | awk '{print $1,$2,$3,$5}'|tr '[:upper:]' '[:lower:]'|sort -k 2
解析:
这里用到好几个命令,包括paste,awk,tr以及sort。paste命令用于合并多个文件的同行数据,如上面两个文件employee和bonus调用paste后合并成
100 Jason Smith 100 $5,000 200 John Doe 200 $500 300 Sanjay Gupta 300 $3,000 400 Ashok Sharma 400 $1,250
paste命令可以使用-d指定合并时加入的符号。比如paste -d : employee bonus则结果变成类似100 Jason Smith :100 $5,000 等。默认合并符号为tab符号,更多paste命令请参照http://snailwarrior.blog.51cto.com/680306/144462/。
awk用于提取除了tab符号的其余4列。
tr命令用于将字符串中所有大写字符转换为小写字符。更多选项参见https://blog.csdn.net/zxnm55/article/details/19040135。
sort命令对字符排序。sort -k 2表示按文件第2个域排序,这里第二个域为姓名,所以是按姓名升序排序。如果要降序排列,则要用sort -k 2r。更多sort命令参见http://www.360doc.com/content/10/0925/15/1107705_56263541.shtml。
三、打印本机交换分区大小
问题:打印本机交换分区大小,输出如下
Swap:1024M
参考答案:
top -n 1|grep Swap|sed 's/k.*//'|awk '{print $1,$2/1000"M"}'
解析:
top 命令显示系统资源占用情况,-n 1表示只调用1次。
grep Swap选取Swap所在行。grep命令执行后结果可能如下:
Swap: 16779884k total, 0k used, 16779884k free, 3268200k cached
sed命令用于字符串的一些正则匹配,这里使用了替换参数,将第1个k以及后面的字符替换成了空白。这样,sed执行后,结果为:
Swap: 16779884
awk命令输出内容,对第二个参数除以1000.
四、用户清理
问题:
清除本机除了当前登陆用户以外的所有用户。
参考答案:
kill $(who -u|grep -v `whoami`|awk '{print $6}'|sort -u)
解析:
who -u显示所有当前用户。grep -v选取当前登录用户以外的所有用户。awk打印用户进程ID。sort -u会删除相同的行。最后用kill命令终止。
五、百度脚本面试题
问题:
1)写脚本实现,可以用shell、perl等。在目录/tmp下找到100个以abc开头的文件,然后把这些文件的第一行保存到文件new中。
参考答案1:
#!/bin/sh for filename in `find /tmp -type f -name "abc*"|head -n 100` do sed -n '1p' $filename>>new done
解析:第一,用到了find命令,其中-type f表示选取普通文件,-name用于设定文件名;第二,head -n 100命令用于取出前100项。第三,sed -n ’1p’用于取出文件的第一行内容。第四,>>new表示追加到文件new中。
参考答案2:
find /tmp -type f -name “abc*” | head -n 100 | xargs head -q -n 1 >> new
问题:
2)写脚本实现,可以用shell、perl等。把文件b中有的,但是文件a中没有的所有行,保存为文件c,并统计c的行数。
参考答案:
grep -vxFf a b | tee c | wc -l
解析:grep选取-v表示不选择匹配的行,-F表示匹配的模式按行分割,-f a表示匹配模式来自文件a,最后表示目标文件b。即grep命令从b中选取a中不存在的行。
tee c命令创建文件c,wc -l命令统计行数。
如果你想搜集更多面试题,可参考下面内容:
shell编程-百度面试题
https://www.doc88.com/p-6542593799085.html
shell编程面试题
https://www.doc88.com/p-9953411882649.html
linux-shell面试题
http://zhangbin.junxilinux.com/?p=724
Shell面试题
https://juejin.im/entry/5bead00151882537347579fa
Shell脚本面试题Top50
https://www.jianshu.com/p/7a08d193cf79
Shell脚本面试题Top50
https://www.doc88.com/p-9952889361809.html
更多学习资料:
有的同学,不喜欢看文章,这里给大家推荐套视频,是阿里的完全免费的,不过需要登录才可以看。
70-个经典的shell-脚本面试问题及解答
70-个经典的shell-脚本面试问题及解答.zip
(16.55 KB, 下载次数: 14)
|
|