一、说明:
打算从B站学习一下shell编程,从很多的课程视频中,挑选了一个:
B站视频地址:
打算开始学习着做着笔记:
这个需要一些Linux基础,还有vim的,如果不太熟练,可以看下我之前的整理的俩个博客:
1、整理一些linux命令必须熟练掌握常的命令(复习+扩展学习Linux命令)
整理一些linux命令必须熟练掌握常的命令(复习+扩展学习Linux命令)
2、Linux下vim/vi 编辑器 命令总结
Linux下vim/vi 编辑器 命令总结
3、学习课件:
这个地址我直接把B站中评论下方分享的弄出来了,如果失效,可以下方评论,我把我下载的分享给你。
下载地址
4、之前的博客:
shell编程学习笔记之–学习第一天
shell编程学习笔记之–学习第二天
shell编程学习笔记之–学习第三天
shell编程学习笔记之一–学习第四天
二、实战演练(几个shell常用命令):
1、sed命令:
Linux sed 命令是利用脚本来处理文本文件。
sed 可依照脚本的指令来处理、编辑文本文件。
Sed 主要用来自动编辑一个或多个文件、简化对文件的反复操作、编写转换程序等。
语法
1 | sed [-hnV][-e<script>][-f<script文件>][文本文件] |
参数说明:
1 | -e<script>或--expression=<script> 以选项中指定的script来处理输入的文本文件。 |
2 | -f<script文件>或--file=<script文件> 以选项中指定的script文件来处理输入的文本文件。 |
3 | -h或--help 显示帮助。 |
4 | -n或--quiet或--silent 仅显示script处理后的结果。 |
5 | -V或--version 显示版本信息。 |
动作说明:
1 | a :新增, a 的后面可以接字串,而这些字串会在新的一行出现(目前的下一行)~ |
2 | c :取代, c 的后面可以接字串,这些字串可以取代 n1,n2 之间的行! |
3 | d :删除,因为是删除啊,所以 d 后面通常不接任何咚咚; |
4 | i :插入, i 的后面可以接字串,而这些字串会在新的一行出现(目前的上一行); |
5 | p :打印,亦即将某个选择的数据印出。通常 p 会与参数 sed -n 一起运行~ |
6 | s :取代,可以直接进行取代的工作哩!通常这个 s 的动作可以搭配正规表示法! |
示例1、将name替换为chinese:
敲入代码:
1 |
|
2 | My name is zhaojiafu |
3 |
|
4 | this is my first sed text |
5 |
|
6 | 127.0.0.1 |
7 |
|
8 | 192.168.2.1 |
运行命令:
查看是否真正修改name.txt
这个是修改在缓存中,并没有真正修改原文件,需要加个参数-i。
1 | sed -i 's/name/chinese/g' name.txt |
再次cat查看,发现修改成功了。
这样就不用打开在vim中进行替换了,vim的末行命令也是可以进行替换操作的。
示例2、在每行开头加入 #id
1 | sed 's/^/& #id/g' name.txt |
本文我没有写入,如果真正写入到文档,加个-i参数。^代表开头。
示例3、在每行末尾加入 #id
$代表末尾。
1 | sed 's/$/& #id/g' name.txt |
示例4、在含有chinese的行后面加入demo111
1 | sed '/chinese/a demo111' name.txt |
代码里面的a代表后面。
示例5、在含有chinese的行前加入demo111
1 | sed '/chinese/i demo111' name.txt |
i代表含有chinese一行的前面加入demo111。
示例6、高级用法:
- 打印出含有chinese的所有行
1 | sed -n '/chinese/p' name.txt |
- 打印文档的第一行:
- 打印文档的1-5行:
- 打印文档的第三行到末尾所有行
- 打印文章的第四行至第六行
1 | sed -n '4p ;6p' name.txt |
- 删除文件的20至末尾所有行:
1 | sed -i '20,$d' num_sort.txt |
示例7、给一个含有数字的文件,提取除最大的和最小的俩个数
num_sort.txt
1 | 12312 2323 32 |
2 | 213 231 |
3 | 23123 |
4 | 21321432423 |
5 | 32131 |
6 |
|
7 |
|
8 | 321312 |
9 | 3 |
10 | 1321 |
11 | 31 |
12 | 32 |
13 | 2132 |
14 | 4 |
15 | 12312 2323 32 |
16 | 213 231 |
17 | 23123 |
18 | 21321432423 |
19 | 32131 |
20 | 321312 |
21 | 3 |
- 第一步:将空格替换成换行符:
- 使用grep将空行去掉:
1 | cat num_sort.txt | sed 's/ /\n/g'| grep -v '^$' |
grep -v 是指去掉后面匹配到的字符串,
‘^$’ 指的是匹配到的空行。
- 排序:
1 | cat num_sort.txt | sed 's/ /\n/g'| grep -v '^$' | sort -nr |
sort -n是从小到大排序,r是至反向,-nr就是从大到小排序。
- 求出最大数和最小数
1 | $cat num_sort.txt | sed 's/ /\n/g'| grep -v '^$' | sort -nr |sed -n '1p;$p' |
2 | 21321432423 |
3 | 3 |
示例8、打印奇数行或偶数行
方法1:
1 | sed -n 'p;n' test.txt |
2 | sed -n 'n;p' test.txt |
方法2:
1 | sed -n '1~2p' test.txt |
2 | sed -n '2~2p' test.txt |
2、grep:
我之前的博客记录的有些笔记。地址
实例:
name.txt文件:
1 | $cat name.txt |
2 |
|
3 | My chinese is zhaojiafu |
4 |
|
5 | this is my first sed text |
6 |
|
7 | 127.0.0.1 |
8 |
|
9 | 192.168.2.1 |
10 | 192.168.2. |
11 |
|
12 | 192.168. |
13 | 192. |
1、匹配:含有127
的行
1 | $cat name.txt |grep '127' |
2 | 127.0.0.1 |
2、匹配含有192
的行:
1 | $cat name.txt |grep '192' |
2 | 192.168.2.1 |
3 | 192.168.2. |
4 | 192.168. |
5 | 192. |
3、匹配只有192.
的:
1 | $cat name.txt |grep '^192\.$' |
2 | 192. |
4、匹配以192
开头.
结尾的行
1 | $cat name.txt |grep '^192.*\.$' |
2 | 192.168.2. |
3 | 192.168. |
4 | 192. |
5、匹配一个ip的正确写法:
视频中的教程讲的有点不全,我这里写个正确的匹配ip的方法。
其中数字肯定不会0开头,一般1-3位,后面都是0-9的数字。
其中-E
代表使用的是正则匹配。
1 | $cat name.txt |grep -E '[1-9][0-9]{0,2}(\.[0-9]{1,3}){3}' |
2 | 127.0.0.1 |
3 | 192.168.2.1 |
6、吧匹配到的行号打印出来:
-n
参数就是匹配到的行号打印出来,前面的6:
和8:
就是第6行和第8行
1 | $cat name.txt |grep -n -E '[1-9][0-9]{0,2}(\.[0-9]{1,3}){3}' |
2 | 6:127.0.0.1 |
3 | 8:192.168.2.1 |
7、egrep
和 grep -E
是一样的。
1 | $grep -E "192|127" name.txt |
2 | 127.0.0.1 |
3 | 192.168.2.1 |
4 | 192.168.2. |
5 | 192.168. |
6 | 192. |
1 | $egrep "192|127" name.txt |
2 | 127.0.0.1 |
3 | 192.168.2.1 |
4 | 192.168.2. |
5 | 192.168. |
6 | 192. |
3、awk:
AWK是一种处理文本文件的语言,是一个强大的文本分析工具。 之所以叫AWK是因为其取了三位创始人 Alfred Aho,Peter
Weinberger, 和 Brian Kernighan 的 Family Name 的首字符。
①、语法
1 | awk [选项参数] 'script' var=value file(s) |
2 | 或 |
3 | awk [选项参数] -f scriptfile var=value file(s) |
②、选项参数说明:
1 | -F fs or --field-separator fs |
2 | 指定输入文件折分隔符,fs是一个字符串或者是一个正则表达式,如-F:。 |
3 | -v var=value or --asign var=value |
4 | 赋值一个用户定义变量。 |
5 | -f scripfile or --file scriptfile |
6 | 从脚本文件中读取awk命令。 |
7 | -mf nnn and -mr nnn |
8 | 对nnn值设置内在限制,-mf选项限制分配给nnn的最大块数目;-mr选项限制记录的最大数目。这两个功能是Bell实验室版awk的扩展功能,在标准awk中不适用。 |
9 | -W compact or --compat, -W traditional or --traditional |
10 | 在兼容模式下运行awk。所以gawk的行为和标准的awk完全一样,所有的awk扩展都被忽略。 |
11 | -W copyleft or --copyleft, -W copyright or --copyright |
12 | 打印简短的版权信息。 |
13 | -W help or --help, -W usage or --usage |
14 | 打印全部awk选项和每个选项的简短说明。 |
15 | -W lint or --lint |
16 | 打印不能向传统unix平台移植的结构的警告。 |
17 | -W lint-old or --lint-old |
18 | 打印关于不能向传统unix平台移植的结构的警告。 |
19 | -W posix |
20 | 打开兼容模式。但有以下限制,不识别:/x、函数关键字、func、换码序列以及当fs是一个空格时,将新行作为一个域分隔符;操作符**和**=不能代替^和^=;fflush无效。 |
21 | -W re-interval or --re-inerval |
22 | 允许间隔正则表达式的使用,参考(grep中的Posix字符类),如括号表达式[[:alpha:]]。 |
23 | -W source program-text or --source program-text |
24 | 使用program-text作为源代码,可与-f命令混用。 |
25 | -W version or --version |
26 | 打印bug报告信息的版本。 |
③、基本用法
创建一个awk_name.txt文件
1 | $cat awk_name.txt |
2 | My name is zhaojiafu1 |
3 | My name is zhaojiafu2 |
4 | My name is zhaojiafu3 |
5 | My name is zhaojiafu4 |
6 | My name is zhaojiafu5 |
7 | My name is zhaojiafu6 |
8 | My name is zhaojiafu7 |
9 | My name is zhaojiafu8 |
10 | My name is zhaojiafu9 |
1】、匹配第一列:
1 | $cat awk_name.txt |awk '{print $1}' |
2 | My |
3 | My |
4 | My |
5 | My |
6 | My |
7 | My |
8 | My |
9 | My |
10 | My |
2】、匹配第1和4列:
1 | $cat awk_name.txt |awk '{print $1,$4}' |
2 | My zhaojiafu1 |
3 | My zhaojiafu2 |
4 | My zhaojiafu3 |
5 | My zhaojiafu4 |
6 | My zhaojiafu5 |
7 | My zhaojiafu6 |
8 | My zhaojiafu7 |
9 | My zhaojiafu8 |
10 | My zhaojiafu9 |
3】、匹配最后一列:
1 | $cat awk_name.txt |awk '{print $NF}' |
2 | zhaojiafu1 |
3 | zhaojiafu2 |
4 | zhaojiafu3 |
5 | zhaojiafu4 |
6 | zhaojiafu5 |
7 | zhaojiafu6 |
8 | zhaojiafu7 |
9 | zhaojiafu8 |
10 | zhaojiafu9 |
4】、匹配到/etc/passwd
下面的用户名
方法一
1 | $cat /etc/passwd |sed "s/:/ /g"|awk '{print $1}' |
2 | root |
3 | bin |
4 | daemon |
5 | adm |
方法二
1 | $cat /etc/passwd |awk -F: '{print $1}' |
2 | root |
3 | bin |
4 | daemon |
5 | adm |
其中-F:
是以:
为切割,默认是空格,也可以以#
或者其他字符为分割,-F#
。
5】、获取本机ip的方法:
方法一:
1 | $ifconfig eth0|grep -E '[1-9][0-9]{0,2}(\.[0-9]{1,3}){3}'|sed 's/ /\n/g'|grep -E '[1-9][0-9]{0,2}(\.[0-9]{1,3}){3}'|head -n 1 |
2 | 58.219.63.68 |
其中:
ifconfig eth0
是为了获取含有ip的一组数据
grep -E '[1-9][0-9]{0,2}(\.[0-9]{1,3}){3}'
是为了获取含有ip地址的一行数据
sed 's/ /\n/g'
是为了将空格全部替换成换行
grep -E '[1-9][0-9]{0,2}(\.[0-9]{1,3}){3}'
是为了提取含有所以ip的行
head -n 1
是为了去第一行(因为第一行才是本机ip地址)
方法二:
我的这个是因为,没有视频中的addr:
,有的话自己在进行一个awk -F:'{print $2}'
提取即可。
1 | $ifconfig eth0|grep -E '[1-9][0-9]{0,2}(\.[0-9]{1,3}){3}'|awk '{print $2}' |
2 | 58.219.63.68 |
6】、打印出服务器的使用率的数值:
1 | $df -h|grep '\/$'|awk '{print $5}'|sed "s/%//g" |
2 | 75 |
7】、在提取的数值起前面加入一段字符串:
方法一:sed
接着上面的数值:
1 | $df -h|grep '\/$'|awk '{print $5}'|sed "s/%//g"|sed "s/^/&使用率:/g" |
2 | 使用率:75 |
方法二:awk
1 | $df -h|grep '\/$'|awk '{print $5}'|sed "s/%//g"|awk '{print "使用率:"$NF}' |
2 | 使用率:75 |
4、find:
之前的博客笔记:地址
实例1、查找指定目录下的.sh文件:
查找:
1 | $find ../day03/ -name "*.sh" |
2 | ../day03/read_line.sh |
3 | ../day03/auto_scp.sh |
4 | ../day03/for_str.sh |
5 | ../day03/for_str2.sh |
6 | ../day03/demo/auto_lamp.sh |
7 | ../day03/demo/for2.sh |
8 | ../day03/demo/backup_mysql.sh |
9 | ../day03/demo/for1.sh |
10 | ../day03/demo/backup_time.sh |
11 | ../day03/while2.sh |
12 | ../day03/while.sh |
实例2、使用exec进行复制:
1 | $find ../day04/ -name "num.sh" -exec cp {} . \; |
其中:
{}
代表前面的返回值,填充到这里,和python字符串填充有点像。
- 后面跟的
\;
是固定搭配,记得前面要和其他字符有空格。1 | $ls |
2 | awk_name.txt name.txt num.sh num_sort.txt sort2.txt sort.txt |
实例3、删除当前的num.sh文件:
1.查找:
1 | $find . -name "num.sh" |
2 | ./num.sh |
1 | $find . -name "num.sh" -exec rm -rf {} \; |
2 | $ls |
3 | awk_name.txt name.txt num_sort.txt sort2.txt sort.txt |
可以看出已经删除成功。
如果最后的\;
和前面的命令没有空格会报错。
报错内容示例: