《Linux命令行与shell脚本编程大全》 第二十章 学习笔记

本文主要是介绍《Linux命令行与shell脚本编程大全》 第二十章 学习笔记,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

第一部分:Linux命令行
《Linux命令行与shell脚本编程大全》 第一章:初识Linux shell
《Linux命令行与shell脚本编程大全》 第二章:走进shell
《Linux命令行与shell脚本编程大全》 第三章:基本的bash shell命令
《Linux命令行与shell脚本编程大全》 第四章:更多的bash shell命令
《Linux命令行与shell脚本编程大全》 第五章:使用Linux环境变量
《Linux命令行与shell脚本编程大全》 第六章:理解Linux文件权限
《Linux命令行与shell脚本编程大全》 第七章:管理文件系统
《Linux命令行与shell脚本编程大全》 第八章:安装软件程序
《Linux命令行与shell脚本编程大全》 第九章:使用编辑器

第二部分:shell脚本编程基础
《Linux命令行与shell脚本编程大全》 第十章:构建基本脚本
《Linux命令行与shell脚本编程大全》 第十一章:使用结构化命令
《Linux命令行与shell脚本编程大全》 第十二章:更多的结构化命令
《Linux命令行与shell脚本编程大全》 第十三章:处理用户输入
《Linux命令行与shell脚本编程大全》 第十四章:呈现数据
《Linux命令行与shell脚本编程大全》 第十五章:控制脚本

第三部分:高级shell编程
《Linux命令行与shell脚本编程大全》 第十六章:创建函数
《Linux命令行与shell脚本编程大全》 第十七章:图形化桌面上的脚本编程
《Linux命令行与shell脚本编程大全》 第十八章:初识sed和gawk
《Linux命令行与shell脚本编程大全》 第十九章:正则表达式
《Linux命令行与shell脚本编程大全》 第二十章:sed进阶
《Linux命令行与shell脚本编程大全》 第二十一章:gawk进阶
《Linux命令行与shell脚本编程大全》 第二十二章:使用其他shell

第四部分:高级shell脚本编程主题
《Linux命令行与shell脚本编程大全》 第二十三章:使用数据库
《Linux命令行与shell脚本编程大全》 第二十四章:使用Web
《Linux命令行与shell脚本编程大全》 第二十五章:使用E-mail
《Linux命令行与shell脚本编程大全》 第二十六章:编写脚本实用工具
《Linux命令行与shell脚本编程大全》 第二十七章:shell脚本编程进阶


第二十章:sed进阶

 

多行命令

sed编辑器包含了3个可用来处理多行文本的命令

1.N:将数据流中的下一行加进来创建一个多行组来处理

2.D:删除多行组中的一行

3.P:打印多行组中的一行

next命令

单行的next命令

n命令会告诉sed编辑器移动到数据流中的下一文本行,而不用重新回到命令的最开始再执行一遍

通常sed编辑器会在移动到数据流中的下一文本行前在这行上执行所有定义好的命令。单行的next命令改变了这一流程

$ cat test.txt 
line1line2line3line4

如果我们想删除line1下面的空行,我们可以先找到line1,然后删除下面的那一行

$ sed -i '/line/{n;d}' test.txt 
$ cat test.txt 
line1
line2
line3line4

发现,不止是line1下面的那行被删除了,line2、line3下面的空白行也被删除了。sed执行完n之后的命令 ,还是要继续逐行扫描的,然后对符合要求的行进行操作。

所以我们得匹配的精确点

$ sed -i '/line1/{n;d}' test.txt 
suzhaoqiang@suzhaoqiang-OptiPlex-380:~/android/source/linux_learned$ cat test.txt 
line1
line2line3line4

合并文本行

单行next命令会将数据流中的下一文本行移动到sed编辑器的工作空间(称为模式空间,pattern space)

多行的next命令 会将下一文本行加到已经在模式空间中的文本上,文本行之间仍用换行分隔

$ cat test.txt 
line1
line2
line3
line4
line5

下面将前两行合并

$ sed -i '/line1/{N;s/\n/ /}' test.txt 
$ cat test.txt 
line1 line2
line3
line4
line5

如果想两行变成一行,那么:

$ sed -i '{N;s/\n/ /}' test.txt

多行删除命令

可以N与d配合使用,注意下面的结果:

$ cat test.txt 
line1
line2
line3
line4
line5
$ sed 'N;/line3/d' test.txt 
line1
line2
line5

发现把模式空间中的line3和line4都删除了

sed还提供D,可以只删除模式空间中的第一行

d清空模式空间

$ sed 'N;/line3/D' test.txt 
line1
line2
line4
line5

多行打印命令

p打印模式空间

P打印模式空间的第一行

$ cat test.txt 
line1
line2
line3
line4
line5
$ sed -n 'N;/line/p' test.txt 
line1
line2
line3
line4
$ sed -n 'N;/line/P' test.txt 
line1
line3

P只打印了模式空间中的第一行,p打印出模式空间中所有内容

 

保持空间

模式空间是sed的一块活动缓冲区,但并不是sed编辑器保存文本唯一空间

sed有一个叫做保持空间(hold space)的另一块缓冲区。可以在处理模式空间中其他行时用保持空间来临时保存一些行。

sed的保持空间命令

命令描述
h将模式空间复制到保持空间
H将模式空间附加到保持空间
g将保持空间复制到模式空间
G将保持空间附加到模式空间
x交换保持空间和模式空间的内容

一个练习,提取文本前两行,组合成line1,line2,line1形式

$ cat test.txt
line1
line2
line3
line4
line5
line6
$ sed -n '/line1/{h;p;n;p;g;p}' test.txt 
line1
line2
line1

先找到第一行,把第一行复制到保持空间,然后打印第一行。接着读取第二行,打印第二行,然后把保持空间复制到模式空间,再次打印模式空间。

我们可以简化一下过程

$ sed -n '1{h;N;G;p}' test.txt 
line1
line2
line1

寻址找到第一行,把第一行复制到保持空间,然后读取第二行追加到模式空间上,再把保持空间追加到模式空间上,最后一起打印。

 

排除命令

叹号命令用来排除命令,让原本会起作用的命令不起作用(我觉得书上的这句话只会误导人……)

man 写道
After the address (or address-range), and before the command, a ! may be inserted, which specifies that the command shall only be executed if the address (or
address-range) does not match.

在地址(或者一个范围)之后,命令之前,可以插入叹号(!),它指定了这个命令只能运行在地址(范围)之外的地方。

还是man讲的清楚一些。

不打印还有数字1,2,3的行

$ cat test.txt
line1
line2
line3
line4
line5
line6
$ sed -n '/[1-3]/!p' test.txt 
line4
line5
line6

下面看一个复杂点的例子,反转文本

1)首先sed读取第一行到模式空间,然后将其复制到保持空间中

2)然后sed读取第二行到模式空间,将保持空间追加到模式空间(模式空间现在为第二行、第一行),再将模式空间复制到保持空间中

然后不断重复步骤2),最后进行打印

$ sed -n '1!G;h;$p' test.txt 
line6
line5
line4
line3
line2
line1
$ tac test.txt
line6
line5
line4
line3
line2
line1

这里为了练习,所以使用sed,否则我们可以使用tac

$ tac test.txt
line6
line5
line4
line3
line2
line1

毕竟sed需要讲所有行都读取出来,然后才能打印,所以有这种工作的时候,不应该使用sed

 

改变流

通常,sed编辑器会从脚本的顶部开始执行命令并一直处理到脚本的结尾(D例外,它会强制sed编辑器返回到脚本顶部,而不是读取新行)

跳转(branch)

格式如下:

[address]b [label]

与叹号类似,b可以作用在一个范围上

label定义了要跳转到的位置,如果没有label,b将跳转到脚本的结尾。

$ sed '2,3b;s/line/Line/;s/Line/lines/' test.txt 
lines1
line2
line3
lines4
lines5
lines6

上面的脚本没有为b定义label,所以两个替换命令都执行了。

下面重写一下反转文本的例子

$ sed -n '1b test;G;:test h;$p' test.txt
line6
line5
line4
line3
line2
line1

上面为b定义了一个label叫做test

如果是第一行,那么就执行h;$p,否则执行G;h;$p

我们也可以用b命令实现简单的循环

下面是一个去掉逗号的例子:

$ echo "This, is, a, test, to, remove, commas." | sed -n '{:start;s/,//p;b start}'
This is, a, test, to, remove, commas.
This is a, test, to, remove, commas.
This is a test, to, remove, commas.
This is a test to, remove, commas.
This is a test to remove, commas.
This is a test to remove commas.

label可以定义在b的前面

现在这个例子就很容易理解了,找到逗号,然后删除,打印,然后跳转到脚本开头重复执行。

当所有逗号都删除了之后,循环依然没有停止,所以需要想办法让它在执行完任务就停止查找。

在重复之前,我们查找逗号,如果有,那么就重复执行。

$ echo "This, is, a, test, to, remove, commas." | sed -n '{:start;s/,//p;/,/b start}'
This is, a, test, to, remove, commas.
This is a, test, to, remove, commas.
This is a test, to, remove, commas.
This is a test to, remove, commas.
This is a test to remove, commas.
This is a test to remove commas.

现在就不会进入死循环了。

但是现在还有一个问题,就是我们只想要最终的结果怎么办?

也就是说,我们不能每次循环的时候都打印,只有在执行完任务的时候才需要打印。

$ echo "This, is, a, test, to, remove, commas." | sed -n '{:start;s/,//;/,/b start;p}'
This is a test to remove commas.

测试

类似跳转命令,测试命令(t)会基于替换命令的输出跳转到一个标签,而不是基于地址跳转到一个标签。

在没有指定标签的情况下,如果测试成功,sed会跳转到脚本的结尾。

$ cat test.txt 
line1
line2
line3
line4
line5
line6
$ sed 's/line[45]/Line/;t;s/line[0-9]/line/' test.txt 
line
line
line
Line
Line
line

如果第一个替换命令成功替换,那么t后面的命令就不再执行,否则执行。

下面改写上面删除逗号的例子:

$ echo "This, is, a, test, to, remove, commas." | sed -n '{:start;s/,//;t start;p}'
This is a test to remove commas.


模式替代

and符号

and符号(&)和正则里面的反向引用很相似。&用来代表替换命令中的匹配模式中匹配到的文本。

$ cat test.txt 
line1
line2
line3
line4
line5
line6
$ sed 's/[0-9]/0&/' test.txt 
line01
line02
line03
line04
line05
line06

替换单独的单词

下面的内容就和java正则里面的反向引用一模一样了。

$ sed 's/\([0-9]\)/0\1/' test.txt 
line01
line02
line03
line04
line05
line06

和java正则不同的是,这里的括号需要转义,正好与正则相反。

下面看看如何给一个数字添加千位分割符

$ echo "1234567" | sed ':start;s/\(.*[0-9]\)\([0-9]\{3\}\)/\1,\2/;t start'
1,234,567
$ echo "12345678" | sed ':start;s/\(.*[0-9]\)\([0-9]\{3\}\)/\1,\2/;t start'
12,345,678
$ echo "123456789" | sed ':start;s/\(.*[0-9]\)\([0-9]\{3\}\)/\1,\2/;t start'
123,456,789

代码看上去挺吓人的,这里圆括号和花括号都需要转义,转义之后的圆括号相当于分组,但是用反斜线+数字来引用,花括号转义之后相当于量词

这段代码的意思是:从开头查找连续的数字,前面的一组,后三个一组,然后在两组之间添加逗号

然后再次循环这段逻辑,由于之前在最后三个数字前面添加了括号,所以这次查找不会找到最后三个数字,这次的两组中的第二组是倒数第4、5、6个数字

我们来看一下java中如何实现这个功能:

String reg1 = "\\d(?=(\\d{3})+$)";
System.out.println("123456789".replaceAll(reg1, "$0,"));
System.out.println("12345678".replaceAll(reg1, "$0,"));
System.out.println("1234567".replaceAll(reg1, "$0,"));

输出:

123,456,789

12,345,678

1,234,567

 

在脚本中使用sed

使用包装脚本

可以包装一下之前写过的脚本

$ cat sed_test
#!/bin/bash
sed -n '1!G;h;$p' "$1"

方便之后的使用

$ cat test.txt
line1
line2
line3
line4
line5
line6
$ sed_test test.txt 
line6
line5
line4
line3
line2
line1

重定向sed的输出

默认,sed会将结果输出到STDOUT中,我们可以在shell中使用反引号将其输出定向到变量中。

 

创建sed实用工具

加倍行间距

$ cat test.txt
line1
line2
line3
$ sed '$!G' test.txt 
line1line2line3

保持空间默认只有一个空行,我们将其追加到模式空间即可

对可能含有空白行的文件加倍行间距

策略是先删除原来的空白行,然后在重复上面的工作即可。

$ sed '/^$/d;$!G' test.txt

给文件中行编号

$ cat test.txt
line1
line2
line3
$ sed '=' test.txt | sed 'N;s/\n/ /'
1 line1
2 line2
3 line3

先给出行号,然后消除行号与行直接的换行即可

打印末尾若干行

打印出最后一行很简单:

$ sed -n '$p' test.txt

打印末尾三行呢?

“滚动窗口(rolling window)”是检验模式空间中文本行组成的块的常用方法。

以打印最后三行为例:

$ cat test.txt 
line1
line2
line3
line4
line5
line6
line7
line8
line9
$ sed ':start;$q;N;4,$D;b start' test.txt 
line7
line8
line9

1.如果当前是最后一行,退出

2.读取下一行

3.如果当前行的行号在3之后,那么就删除模式空间中的第一行

4.重复上面的操作

这里sed会先读取前三行,读取第四行之后,删除第一行,读取第五行之后,删除第二行……

注意:如果当前行在4,$中,那么就执行D

如果我们想除了前三行,其余行都打印,那么可以这样:

$ sed ':start;$q;N;1,4D;b start' test.txt 
line4
line5
line6
line7
line8
line9

删除行

删除连续的空白行

关键在于如何找到空行与非空行的交界处

$ sed '/./,/^$/!d' test.txt

点能匹配到非空行,非空行与第一个空行直接的行不删除,其余行删除即可。

当然,这里如果开头有空行,也会被删除掉的

删除开头的空白行

$ sed '/./,$!d' test.txt

这个就比较简单了,从第一个非空行到最后一行,不删除,其余的全删除即可。

删除结尾的空白行

$ sed '{
> :start
> /^\n*$/{$d;N;b start}
> }' test.txt

注意:这里有两层花括号,中间的花括号只作用在前面指定的行上,可以看作是一组命令

如果当前行是空行,那么模式匹配成功,进入括号中的命令组

如果是最后一行,那么删除,否定读取下一行到模式空间,然后重复上面的步骤

如果读取的行不是空行,那么模式匹配失败,不再进入后面的命令组,sed继续处理下一行

删除HTML标签

在sed中,没有惰性匹配,所有我们不能使用.*?这种形式,当然,下面这种直白的贪婪模式也肯定是错的

$ sed 's/<.*>//g' test.html

我们简单的模拟一下惰性匹配:
$ sed 's/<[^>]*>//g' test.html
最后,如果你愿意,可以加一个删除空行的处理:
$ sed 's/<[^>]*>//g;/^$/d' test.html



转贴请保留以下链接

本人blog地址

http://su1216.iteye.com/

http://blog.csdn.net/su1216/

这篇关于《Linux命令行与shell脚本编程大全》 第二十章 学习笔记的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/694478

相关文章

HarmonyOS学习(七)——UI(五)常用布局总结

自适应布局 1.1、线性布局(LinearLayout) 通过线性容器Row和Column实现线性布局。Column容器内的子组件按照垂直方向排列,Row组件中的子组件按照水平方向排列。 属性说明space通过space参数设置主轴上子组件的间距,达到各子组件在排列上的等间距效果alignItems设置子组件在交叉轴上的对齐方式,且在各类尺寸屏幕上表现一致,其中交叉轴为垂直时,取值为Vert

Ilya-AI分享的他在OpenAI学习到的15个提示工程技巧

Ilya(不是本人,claude AI)在社交媒体上分享了他在OpenAI学习到的15个Prompt撰写技巧。 以下是详细的内容: 提示精确化:在编写提示时,力求表达清晰准确。清楚地阐述任务需求和概念定义至关重要。例:不用"分析文本",而用"判断这段话的情感倾向:积极、消极还是中性"。 快速迭代:善于快速连续调整提示。熟练的提示工程师能够灵活地进行多轮优化。例:从"总结文章"到"用

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

linux-基础知识3

打包和压缩 zip 安装zip软件包 yum -y install zip unzip 压缩打包命令: zip -q -r -d -u 压缩包文件名 目录和文件名列表 -q:不显示命令执行过程-r:递归处理,打包各级子目录和文件-u:把文件增加/替换到压缩包中-d:从压缩包中删除指定的文件 解压:unzip 压缩包名 打包文件 把压缩包从服务器下载到本地 把压缩包上传到服务器(zip

学习hash总结

2014/1/29/   最近刚开始学hash,名字很陌生,但是hash的思想却很熟悉,以前早就做过此类的题,但是不知道这就是hash思想而已,说白了hash就是一个映射,往往灵活利用数组的下标来实现算法,hash的作用:1、判重;2、统计次数;

Linux 网络编程 --- 应用层

一、自定义协议和序列化反序列化 代码: 序列化反序列化实现网络版本计算器 二、HTTP协议 1、谈两个简单的预备知识 https://www.baidu.com/ --- 域名 --- 域名解析 --- IP地址 http的端口号为80端口,https的端口号为443 url为统一资源定位符。CSDNhttps://mp.csdn.net/mp_blog/creation/editor

【Python编程】Linux创建虚拟环境并配置与notebook相连接

1.创建 使用 venv 创建虚拟环境。例如,在当前目录下创建一个名为 myenv 的虚拟环境: python3 -m venv myenv 2.激活 激活虚拟环境使其成为当前终端会话的活动环境。运行: source myenv/bin/activate 3.与notebook连接 在虚拟环境中,使用 pip 安装 Jupyter 和 ipykernel: pip instal

零基础学习Redis(10) -- zset类型命令使用

zset是有序集合,内部除了存储元素外,还会存储一个score,存储在zset中的元素会按照score的大小升序排列,不同元素的score可以重复,score相同的元素会按照元素的字典序排列。 1. zset常用命令 1.1 zadd  zadd key [NX | XX] [GT | LT]   [CH] [INCR] score member [score member ...]

【机器学习】高斯过程的基本概念和应用领域以及在python中的实例

引言 高斯过程(Gaussian Process,简称GP)是一种概率模型,用于描述一组随机变量的联合概率分布,其中任何一个有限维度的子集都具有高斯分布 文章目录 引言一、高斯过程1.1 基本定义1.1.1 随机过程1.1.2 高斯分布 1.2 高斯过程的特性1.2.1 联合高斯性1.2.2 均值函数1.2.3 协方差函数(或核函数) 1.3 核函数1.4 高斯过程回归(Gauss