使用 sed 删除多行字符串的简单方法

Posted

技术标签:

【中文标题】使用 sed 删除多行字符串的简单方法【英文标题】:Simple way to remove multi-line string using sed 【发布时间】:2021-11-18 17:41:37 【问题描述】:

使用 sed,有没有办法根据一些开始和结束表达式从文本文件中删除多行?

我知道文件中的标记,并想删除(包括标记)之间的所有内容。我已经看到了一些非常复杂的解决方案,我想在不求助于微命令的情况下做到这一点。

我的文件看起来像这样:

cat /tmp/foobar.txt
this is line 1

this is line 3

tomcat.util.scan.StandardJarScanFilter.jarsToSkip=\
annotations-api.jar,\
ant-junit*.jar,\
ant-launcher.jar,\
ant.jar,\
asm-*.jar,\
aspectj*.jar,\
bootstrap.jar,\
catalina-ant.jar,\
catalina-ha.jar,\
catalina-ssi.jar,\
catalina-storeconfig.jar

the end leave me
and me

我想删除从 tomcat.util 开始到最后一个 .jar 的所有内容

【问题讨论】:

【参考方案1】:

tldr;

我认为这是最简单的方法,不需要像微命令这样的程序集

sed '/^tomcat\.util.*$/,/^.*[^\]$/d' /tmp/foobar.txt

产生

this is line 1

this is line 3


the end leave me
and me

如果您想删除文件中的行而不是将输出输出到标准输出,请使用inline 标志,所以

sed -i '/^tomcat\.util.*$/,/^.*[^\]$/d' /tmp/foobar.txt

那么...这是如何工作的?

sed 命令,如vi 命令在address 上运行。通常我们不指定地址,而只是将命令应用于文件的所有行,例如,在我们通常会做的文件中将the 替换为that

sed -i 's/the/that/g' /tmp/foobar.txt

即对文件中的所有行应用替换或s 命令。

在这种情况下,您希望删除一些行,以便我们可以使用 delete 或 d 命令。但是我们需要告诉它在哪里删除。所以我们需要给它一个地址。

sed 命令的格式是

[addr][!]command[options]

(见the docs)

如果没有指定地址,则该命令应用于所有行,如果指定了!,则该命令应用于所有与该模式不匹配的行。到目前为止一切顺利。

这里的诀窍是addr 可以是单个地址或地址范围。地址可以是行号或正则表达式模式。您在两个地址之间使用, 来指定范围。

所以你可以删除第 5 到 8 行(包括)

sed -i '5,8d' /tmp/foobar.txt

在这种情况下,我们知道一些“标记”,而不是知道行号,我们可以使用正则表达式,所以第一个标记,以tomcat.util 开头的行被正则表达式找到

/^tomcat\.util.*$/

第二个标记有点棘手,但如果我们看一下,我们可以看到要删除的最后一行是第一个不以 \ 结尾的行,因此我们可以匹配包含“除了不以\结尾"

/^.*[^\]$/

虽然如果我们从这两个正则表达式中创建一个范围,第二个标记可以匹配一大堆行,但该范围意味着第二个“地址”是与正则表达式匹配的第一个地址之后的第一行。

综上所述,我们要删除 (d) 范围内的所有行987654347@即

sed '/^tomcat\.util.*$/,/^.*[^\]$/d' /tmp/foobar.txt

希望有帮助 ;-)

干杯

卡尔

【讨论】:

不用担心。干杯。 tomcat.util 行不以 `` 结尾时,下一行也会被删除。【参考方案2】:

对于跨行的任何内容,Awk 通常比 sed 更有用。在每个 Unix 机器上的任何 shell 中使用任何 awk:

$ awk '!/\.jar/f=0 /tomcat\.util/f=1 !f' file
this is line 1

this is line 3


the end leave me
and me

【讨论】:

谢谢!这也有效。我不得不说我什至没有想到awk,你说得对,这个解决方案既好又干净。【参考方案3】:

这可能对你有用(GNU sed):

sed -n '/tomcat\.util/:a;n;/\.jar/ba;p' file

使用-n 选项关闭隐式打印。

匹配包含tomcat.util的行。

继续获取行,直到这样的行与包含 .jar 的行不匹配。

打印所有其他行。


替代方案:

sed -E '/tomcat\.util/:a;$!N;/\.jar(,\\)?$/s/\n//;ta;D' file

收集以tomcat.util 开头并以.jar,\.jar 结尾的行,删除换行符直到文件结尾或不匹配,然后删除该集合。

【讨论】:

以上是关于使用 sed 删除多行字符串的简单方法的主要内容,如果未能解决你的问题,请参考以下文章

sed 命令简单使用方法

sed简单使用选择性删除

sed多行文本处理

sed简单使用替换

LINUX三剑客sed

sed 匹配多行,在行首添加字符