sed 多行模式、分支及循环

目录

1. 读取下一行数据并附加到模式空间(命令 N)

2. 打印多行模式中的第一行(命令 P)

3. 删除多行模式中的第一行(命令 D)

4. 循环和分支(命令 b 和 :label 标签)

5. 使用命令 t 进行循环


        sed 默认每次只处理一行数据,除非使用 H、G 或者 N 等命令创建多行模式,每行之间用换行符分开。本篇将解释适用于多行模式的 sed 命令。在处理多行模式时,要记住 ^ 只匹配该模式的开头,即最开始一行的开头,且 $ 只匹配该模式的结尾,即最后一行的结尾。

1. 读取下一行数据并附加到模式空间(命令 N)

        就像 H 和 G 一样,大写的命令只会追加内容而不是替换内容。命令 N 从输入文件中读取下一行并追加到模式空间,而不是替换模式空间。
        小写命令 n 打印当前模式空间的内容,并清空模式空间,从输入文件中读取下一行到模式空间,然后继续执行后面的命令。大写命令 N 不会打印模式空间内容,也不会清除模式空间内容,而是在当前模式空间内容后加上换行符 \n,并且从输入文件中读取下一行数据,追加到模式空间中,然后继续执行后面的命令。
        在下面的例子中,以冒号分隔,打印员工名称和职位。示例文本 empnametitle.txt 的内容如下:

John Doe
CEO
Jason Smith
IT Manager
Raj Reddy
Sysadmin
Anand Ram
Developer
Jane Miller
Sales Manager

        在这个文件中,每个员工的姓名和职位位于连续的两行内。下面的命令在同一行上打印以冒号分割的员工名称和职位。

#sed -e '{N;s/\n/:/}' empnametitle.txt
John Doe:CEO
Jason Smith:IT Manager
Raj Reddy:Sysadmin
Anand Ram:Developer
Jane Miller:Sales Manager
#

        本例中:

  • N 追加换行符 \n 到当前模式空间(员工名称)的最后,然后从输入文件读取下一行数据并追加进来。因此,当前模式空间内容变为“员工名称\n员工职位”。
  • s/\n/:/ 把换行符 \n 替换为冒号,作为员工名称和员工职位的分隔符。
     

        下面的例子在每行文本行首添加行号。示例文件 employee.txt 文件内容如下:

101,John Doe,CEO
102,Jason Smith,IT Manager
103,Raj Reddy,Sysadmin
104,Anand Ram,Developer
105,Jane Miller,Sales Manager

        本例演示在打印 employee.txt 文件内容的同时,以文本方式显示每行的行号:

#sed -e '=' employee.txt | sed '{N;s/\n/ /}'
1 101,John Doe,CEO
2 102,Jason Smith,IT Manager
3 103,Raj Reddy,Sysadmin
4 104,Anand Ram,Developer
5 105,Jane Miller,Sales Manager
#

        命令 = 在每个原始行的前面添加一行行号:

#sed -e '=' employee.txt
1
101,John Doe,CEO
2
102,Jason Smith,IT Manager
3
103,Raj Reddy,Sysadmin
4
104,Anand Ram,Developer
5
105,Jane Miller,Sales Manager
#

        命令 N 在当前模式空间后面加上 \n(当前模式空间内容为行号),然后读取下一行,并追加到模式空间中。因此,模式空间内容变为“行号\n原始内容”。然后用 s/\n/ / 把换行符 \n 替换成空格。

2. 打印多行模式中的第一行(命令 P)

        大写的 D、P 功能和小写的 d、p 非常相似,但它们在多行模式中有特殊的功能。小写的命令 p 打印模式空间的内容,大写的 P 也打印模式空间内容,直到它遇到换行符 \n。

        下面的例子将打印示例文本 empnametitle.txt 中所有管理者的名称:

#sed -n -e 'N' -e '/Manager/P' empnametitle.txt
Jason Smith
Jane Miller
#
  • N 追加换行符 \n 到当前模式空间(员工名称)的最后,然后从输入文件读取下一行数据并追加进来。因此,当前模式空间内容变为“员工名称\n员工职位”。
  • /Manager/P 打印匹配 Manager 的行,并且只打印员工名称。
     

3. 删除多行模式中的第一行(命令 D)

        小写命令 d 会删除模式空间内容,然后读取下一条记录到模式空间,并忽略其后的命令,从头开始下一次循环。大写命令 D,既不会读取下一条记录,也不会完全清空模式空间(除非模式空间内只有一行)。它只会:

  • 删除模式空间的部分内容,直到遇到换行符 \n。
  • 忽略后续命令,在当前模式空间中从头开始执行命令。

        假设有下面内容的文件 empnametitle-with-commnet.txt,每个员工的职位都用 @ 包含起来作为注释。需要注意的是,有些注释是跨行的,如 @Information Technology officer@ 就跨了两行。

John Doe
CEO @Chief Executive Officer@
Jason Smith
IT Manager @Infromation Technology
Officer@
Raj Reddy
Sysadmin @System Administrator@
Anand Ram
Developer @Senior
Programmer@
Jane Miller
Sales Manager @Sales
Manager@

        现在的目标是去掉文件里的注释:

#sed -e '/@/{N;/@.*@/{s/@.*@//;P;D}}' empnametitle-with-commnet.txt
John Doe
CEO 
Jason Smith
IT Manager 
Raj Reddy
Sysadmin 
Anand Ram
Developer 
Jane Miller
Sales Manager 
#

        注意这里不能加 -n 选项,因为 P 命令打印的只有职位(因为只有职位带注释):

#sed -n -e '/@/{N;/@.*@/{s/@.*@//;P;D}}' empnametitle-with-commnet.txt
CEO 
IT Manager 
Sysadmin 
Developer 
Sales Manager 
#

        也可把上述命令写到 sed 脚本中然后执行:

  1. 创建内容如下的脚本文件 D-upper.sed
    #!/bin/sed -f
    /@/{
    N
    /@.*@/{s/@.*@//;P;D}
    }

  2. 修改脚本文件的模式为可执行
    chmod u+x D-upper.sed

  3. 执行脚本

    #./D-upper.sed empnametitle-with-commnet.txt
    John Doe
    CEO 
    Jason Smith
    IT Manager 
    Raj Reddy
    Sysadmin 
    Anand Ram
    Developer 
    Jane Miller
    Sales Manager 
    #

        本例中:

  • /@/{ 是外传循环。sed 搜索包含 @ 符号的任意行,如果找到,就执行后面的命令;如果没有找到,则读取下一行。
  • N 从输入文件读取下一行,并追加到模式空间。
  • /@.*@/ 在模式空间中搜索匹配 /@.*@/ 的模式,即以 @ 开头和结尾的任何内容。
  • s/@.*@//;P;D 这个中的替换命令把整个注释替换为空(相当于删除)。P 打印模式空间中的第一行,然后 D 删除模式空间中的第一行。然后从头开始执行命令,即不读取下一条记录,又返回到 /@/ 处执行命令。
     

        完整的执行流程如下表所示。

循环次数

模式空间

操作

1

John Doe

打印 John Doe =>

2

CEO @Chief Executive Officer@

CEO @Chief Executive Officer@\nJason Smith

CEO \nJason Smith

CEO \nJason Smith

Jason Smith

N =>

s/@.*@// =>

P CEO  =>

D =>

打印 Jason Smith =>

3

IT Manager @Infromation Technology

IT Manager @Infromation Technology\nOfficer@

IT Manager

IT Manager

N =>

s/@.*@// =>

P IT Manager  =>

D =>

4

Raj Reddy

打印 Raj Reddy =>

5

Sysadmin @System Administrator@

Sysadmin @System Administrator@\nAnand Ram

Sysadmin \nAnand Ram

Sysadmin \nAnand Ram

N =>

s/@.*@// =>

P Sysadmin  =>

D =>

6

Developer @Senior

Developer @Senior\nProgrammer@

Developer

Developer

N =>

s/@.*@// =>

P Developer  =>

D =>

7

Jane Miller

打印 Jane Miller =>

8

Sales Manager @Sales

Sales Manager @Sales\nManager@

Sales Manager

Sales Manager

N =>

s/@.*@// =>

P Sales Manager  =>

D =>

        对于这个例子而言,可以有以下更简单的写法:

#sed -e '/@/{N;s/@.*@//}' empnametitle-with-commnet.txt
John Doe
CEO 
Jason Smith
IT Manager 
Raj Reddy
Sysadmin 
Anand Ram
Developer 
Jane Miller
Sales Manager 
#

        因为注释固定占一行或两行,所以匹配到 @ 就执行 N,取下一行数据到模式空间,然后整体替换掉注释内容即可。这种写法与上面的 P D 写法输出相同,但执行逻辑不同。

        完整的执行流程如下表所示。

循环次数

模式空间

操作

1

John Doe

打印 John Doe =>

2

CEO @Chief Executive Officer@

CEO @Chief Executive Officer@\nJason Smith

CEO \nJason Smith

N =>

s/@.*@// =>

打印 CEO \nJason Smith =>

3

IT Manager @Infromation Technology

IT Manager @Infromation Technology\nOfficer@

IT Manager

N =>

s/@.*@// =>

打印 IT Manager  =>

4

Raj Reddy

打印 Raj Reddy =>

5

Sysadmin @System Administrator@

Sysadmin @System Administrator@\nAnand Ram

Sysadmin \nAnand Ram

N =>

s/@.*@// =>

打印 Sysadmin \nAnand Ram =>

6

Developer @Senior

Developer @Senior\nProgrammer@

Developer

N =>

s/@.*@// =>

打印 Developer  =>

7

Jane Miller

打印 Jane Miller =>

8

Sales Manager @Sales

Sales Manager @Sales\nManager@

Sales Manager

N =>

s/@.*@// =>

打印 Sales Manager  =>

4. 循环和分支(命令 b 和 :label 标签)

        使用标签和分支命令 b,可以改变 sed 的执行流程:

  • :label 定义一个标签。
  • b lable 执行该标签后面的命令。sed 会跳转到该标签,然后执行后面的命令。
  • 命令 b 后面可以不跟任何标签,这种情况下,它会直接跳到 sed 脚本的结尾。

        下面例子将把 empnametitle.txt 文件中的员工名称和职位合并到一行内,字段之间以冒号 : 分隔,并且在管理者的名称前面加上一个星号 *。sed 脚本文件 label.sed 内容如下:

#!/bin/sed -nf
h;n;H;x
s/\n/:/
/Manager/!b end
s/^/*/
:end
p

        这个脚本中,鉴于之前的例子,已经知道 h;n;H;x 和 s/\n/:/ 的作用了。下面是关于分支的操作:

  • /Manager/!b end 的作用是如果行内不包含关键字 Manager,则跳转到 end 标签(可以任意设置想要的标签名称)。因此,只有匹配 Manager 的员工名称签名,才会执行 s/^/*/ 即在行首加星号 *。
  • :end 即是标签。

        给这个脚本加上可执行权限,然后执行:

#chmod u+x label.sed
#./label.sed empnametitle.txt 
John Doe:CEO
*Jason Smith:IT Manager
Raj Reddy:Sysadmin
Anand Ram:Developer
*Jane Miller:Sales Manager
#

        h;n;H;x 可以用一个 N 替代,这样就不用使用保持空间了。而且这个例子只是为了说明命令 b 如何运行,但它不是必须的,等效的简单写法如下:

#sed -n -e 'N;s/\n/:/g;/Manager/s/^/*/g;p;' empnametitle.txt 
John Doe:CEO
*Jason Smith:IT Manager
Raj Reddy:Sysadmin
Anand Ram:Developer
*Jane Miller:Sales Manager
#

5. 使用命令 t 进行循环

        命令 t 的作用是,如果前面的命令执行成功,那么就跳转到 t 指定的标签处,继续往下执行后续命令。否则,仍然继续正常的执行流程。
        下面例子将把 empnametitle.txt 文件中的员工名称和职位合并到一行内,字段之间以冒号 : 分隔,并且在管理者的名称前面加上三个星号 *。其实只需把上个例子中的替换命令改为 s/^/***/ 即可达到该目的,这里仅仅是为了解释命令 t 是如何运行的。

        创建脚本文件 label-t.sed,内容如下:

#!/bin/sed -nf
h;n;H;x
s/\n/:/
:repeat
/Manager/s/^/*/
/\*\*\*/! t repeat
p

        然后给脚本文件加上可执行权限并执行:

#chmod u+x label-t.sed
#./label-t.sed empnametitle.txt 
John Doe:CEO
***Jason Smith:IT Manager
Raj Reddy:Sysadmin
Anand Ram:Developer
***Jane Miller:Sales Manager
#

        本例中的下面代码执行循环:

:repeat
/Manager/s/^/*/
/\*\*\*/! t repeat
  • /Manager/s/^/*/ 的作用是如果匹配到 Manager,在行首加上星号 *
  • /\*\*\*/!t repeat 的作用是如果没有匹配到三个连续的星号 *,并且前面一行的替换命令成功执行了,则跳转到名为 repeat 的标签处。
  • :repeat 即是标签。
     

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/777376.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

MAX98357、MAX98357A、MAX98357B小巧、低成本、PCM D类IIS放大器,具有AB类性能中文说明规格书

前言: MAX98357A支持标准I2S数据,MAX98357B支持左对齐数字音频数据。两个版本均支持8通道TDM音频数据。 IIS数字功放MAX98357开发板/评估系统 MAX98357 WLP-9(1.347x1.437mm)封装的外观和丝印AKM MAX98357 TQFN-16-EP(3x3mm)封装的外观和丝印AKK 引脚说…

Rust: polars行遍历,从dataframe到struct及Bar设计比较

pandas提供了iterrows()、itertuples()、apply等行遍历的方式,还是比较方便的。 polars的列操作功能非常强大,这个在其官网上有详细的介绍。由于polars底层的arrow是列存储模式,行操作效率低下,官方也不推荐以行方式进行数据操作。…

谷粒商城 - 树形菜单递归流查询、三级分类数据查询性能优化、Jmter 性能压测

目录 树形分类菜单(递归查询,强扩展) 1)需求 2)数据库表设计 3)实现 4)关于 asSequence 优化 性能压测 1)Jmeter 安装使用说明 2)中间件对性能的影响 三级分类数…

昇思25天学习打卡营第5天|GAN图像生成

文章目录 昇思MindSpore应用实践基于MindSpore的生成对抗网络图像生成1、生成对抗网络简介零和博弈 vs 极大极小博弈GAN的生成对抗损失 2、基于MindSpore的 Vanilla GAN3、基于MindSpore的手写数字图像生成导入数据数据可视化模型训练 Reference 昇思MindSpore应用实践 本系列…

01 企业网站架构部署于优化之Web基础与HTTP协议

目录 1.1 Web基础 1.1.1 域名和DNS 1. 域名的概念 2. Hosts文件 3. DNS 4. 域名注册 1.1.2 网页与HTML 1. 网页概述 2. HTML概述 3. HTML基本标签 4. 网站和主页 5. Web1.0与Web2.0 1.1.3 静态网页与动态网页 1. 静态网页 2. 动态网页 3. 动态网页语言 1.2 HTTP协议 1…

如何快速开展每日待办工作 待办任务高效管理

每天,我们都需要处理大量的待办工作,如何高效有序地开展这些工作成为了我们必须要面对的问题。仅仅依靠个人的记忆和脑力去管理这些繁杂的事务,显然是一项艰巨的挑战。在这个时候,如果能有一款实用的待办工具来辅助我们&#xff0…

7年跨境业务资深从业者的代理IP使用经验分享

作为一个拥有7年跨境业务经验的资深从业者,今天大家分享一下在使用各种代理IP服务中的宝贵经验。无论你是新手还是老手,这篇文章都能为你带来一些新的启发和实用技巧。 在我刚开始跨境业务的那几年,最大的挑战之一就是如何跨境访问&#xff0…

ORB 特征点提取

FAST关键点 选取像素p,假设它的亮度为Ip; . 设置一个阈值T(比如Ip的20%); 以像素p为中心,选取半径为3的圆上的16个像素点; 假如选取的圆上,有连续的N个点的亮度大于IpT或小于…

CSS实现图片裁剪居中(只截取剪裁图片中间部分,图片不变形)

1.第一种方式:(直接给图片设置:object-fit:cover;) .imgbox{width: 100%;height:200px;overflow: hidden;position: relative;img{width: 100%;height: 100%; //图片要设置高度display: block;position: absolute;left: 0;right…

【Python基础篇】你了解python中运算符吗

文章目录 1. 算数运算符1.1 //整除1.2 %取模1.3 **幂 2. 赋值运算符3. 位运算符3.1 &&#xff08;按位与&#xff09;3.2 |&#xff08;按位或&#xff09;3.3 ^&#xff08;按位异或&#xff09;3.4 ~&#xff08;按位取反&#xff09;3.5 <<&#xff08;左移&#…

【JavaWeb程序设计】JSP编程II

目录 一、输入并运行下面的import_test.jsp页面 1.1 代码运行结果 1.2 修改编码之后的运行结果 二、errorPage属性和isErrorPage属性的使用 2.1 下面的hello.jsp页面执行时将抛出一个异常&#xff0c;它指定了错误处理页面为errorHandler.jsp。 2.1.2 运行截图 2.2 下面…

压测工具---Ultron

压测工具&#xff1a;Ultron 类型&#xff1a;接口级和全链路 接口级 对于接口级别的压测我们可以进行 http接口压测、thrift压测、redis压测、kafka压测、DDMQ压测、MySQL压测等&#xff0c;选对对应的业务线、选择好压测执行的时间和轮数就可以执行压测操作了 全链路 对…

Java新特性梳理——Java15

highlight: xcode theme: vuepress 概述 2020 年 9 月 15 日&#xff0c;Java 15 正式发布&#xff0c;(风平浪静的一个版本)共有 14 个 JEP&#xff0c;是时间驱动形式发布的第六个版本。相关文档&#xff1a;https://openjdk.java.net/projects/jdk/15/ 语法层面变化 密封类 …

【机器学习】基于密度的聚类算法:DBSCAN详解

&#x1f308;个人主页: 鑫宝Code &#x1f525;热门专栏: 闲话杂谈&#xff5c; 炫酷HTML | JavaScript基础 ​&#x1f4ab;个人格言: "如无必要&#xff0c;勿增实体" 文章目录 基于密度的聚类算法&#xff1a;DBSCAN详解引言DBSCAN的基本概念点的分类聚类过…

JVM原理(十七):JVM虚拟机即时编译器详解

编译器无论在何时、在何种状态下把Class文件转换成与本地基础设施相关的二进制机器码&#xff0c;他都可以视为整个编译过程的后端。 后端编译器编译性能的好坏、代码优化质量的高低却是衡量一款商用虛拟机优秀与否的关键指标之一。 1. 即时编译器 即时编译器是一个把Java的…

19.【C语言】初识指针(重难点)

内存&#xff1a;所有程序的运行在内存中 用Cheat Engine查看任意程序的内存(16进制&#xff09;&#xff1a; 显示大量的数据 想要定位某个数字 &#xff0c;需要知道地址(类比二维坐标) 如F8的地址为00BCB90008,所以是00BCB908(偏移) ctrlG 则有 内存单元的说明&#xff1…

动态颤抖的眼睛效果404页面源码

动态颤抖的眼睛效果404页面源码&#xff0c; 源码由HTMLCSSJS组成&#xff0c;记事本打开源码文件可以进行内容文字之类的修改&#xff0c;双击html文件可以本地运行效果&#xff0c;也可以上传到服务器里面&#xff0c;重定向这个界面 动态颤抖的眼睛效果404页面源码

Portainer 是一个开源的容器管理平台-非常直观好用的Docker图形化项目

在这个容器化技术大行其道的时代&#xff0c;Docker和Kubernetes几乎成了技术圈的新宠。可是管理起容器来&#xff0c;有时候还是有点头大。命令行操作对于某些小伙伴来说&#xff0c;可能还是有点不太友好。 今天开源君分享一个叫 Portainer 的开源项目&#xff0c;一个用来简…

AI大模型时代的存储发展趋势

从2022年下半年&#xff0c;大模型和AIGC这两个词变得极其火热&#xff0c;而GPU的市场也是一卡难求。对于这种迷乱和火热&#xff0c;让我想起了当年的比特币挖矿和IPFS。似乎世界一年一个新风口&#xff0c;比特币、元宇宙、NFT、AIGC&#xff0c;金钱永不眠&#xff0c;IT炒…

【React】React18 Hooks 之 useReducer

目录 useReducer案例1&#xff1a;useReducer不带初始化函数案例2&#xff1a;useReducer带初始化函数注意事项1&#xff1a;dispatch函数不会改变正在运行的代码的状态注意事项2&#xff1a;获取dispatch函数触发后 JavaScript 变量的值注意事项3&#xff1a;触发了reducer&am…