使用 sed 删除多行字符串的简单方法
Simple way to remove multi-line string using sed
使用 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
的所有内容
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
命令应用于文件中的所有行。
在这种情况下,您想要删除 一些行,以便我们可以使用删除或d
命令。但是我们需要告诉它在哪里删除。所以我们需要给它一个地址。
sed
命令的格式是
[addr][!]command[options]
(参见 the docs)
如果未指定地址,则命令将应用于所有行,如果指定了 !
,则将其应用于与模式不匹配的所有行。到目前为止一切顺利。
这里的技巧是 addr
可以是单个地址或地址范围。地址可以是行号或正则表达式模式。您在两个地址之间使用 ,
来指定范围。
所以要删除第 5 行到第 8 行,您可以这样做
sed -i '5,8d' /tmp/foobar.txt
在这种情况下,我们知道一些“标记”而不是知道行号,我们可以改用 Regex,因此第一个标记,以 tomcat.util
开头的行由 regex
/^tomcat\.util.*$/
第二个标记有点棘手,但如果我们看一下,我们可以看到要删除的最后一行是第一个不以 \
结尾的行,因此我们可以匹配包含以下内容的行的“任何但不以 \
”结尾的
/^.*[^\]$/
虽然如果我们从这两个正则表达式中创建一个范围,第二个标记可以匹配一大堆行,但该范围意味着第二个“地址”是第一个匹配正则表达式的地址之后的第一行。
综上所述,我们要删除 (d
) 正则表达式匹配以 tomcat.util
开头并以一行结尾的行找到的地址范围内的所有行不以 \
结尾,即
sed '/^tomcat\.util.*$/,/^.*[^\]$/d' /tmp/foobar.txt
希望对您有所帮助 ;-)
干杯
卡尔
这可能适合您 (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
结束的行,删除换行符直到文件结尾或不匹配,然后删除集合。
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
使用 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
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
命令应用于文件中的所有行。
在这种情况下,您想要删除 一些行,以便我们可以使用删除或d
命令。但是我们需要告诉它在哪里删除。所以我们需要给它一个地址。
sed
命令的格式是
[addr][!]command[options]
(参见 the docs)
如果未指定地址,则命令将应用于所有行,如果指定了 !
,则将其应用于与模式不匹配的所有行。到目前为止一切顺利。
这里的技巧是 addr
可以是单个地址或地址范围。地址可以是行号或正则表达式模式。您在两个地址之间使用 ,
来指定范围。
所以要删除第 5 行到第 8 行,您可以这样做
sed -i '5,8d' /tmp/foobar.txt
在这种情况下,我们知道一些“标记”而不是知道行号,我们可以改用 Regex,因此第一个标记,以 tomcat.util
开头的行由 regex
/^tomcat\.util.*$/
第二个标记有点棘手,但如果我们看一下,我们可以看到要删除的最后一行是第一个不以 \
结尾的行,因此我们可以匹配包含以下内容的行的“任何但不以 \
”结尾的
/^.*[^\]$/
虽然如果我们从这两个正则表达式中创建一个范围,第二个标记可以匹配一大堆行,但该范围意味着第二个“地址”是第一个匹配正则表达式的地址之后的第一行。
综上所述,我们要删除 (d
) 正则表达式匹配以 tomcat.util
开头并以一行结尾的行找到的地址范围内的所有行不以 \
结尾,即
sed '/^tomcat\.util.*$/,/^.*[^\]$/d' /tmp/foobar.txt
希望对您有所帮助 ;-)
干杯
卡尔
这可能适合您 (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
结束的行,删除换行符直到文件结尾或不匹配,然后删除集合。
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