Awk 删除搜索模式之间的文本/行

Awk 删除搜索模式之间的文本/行,awk,sed,Awk,Sed,编码删除整行代码很容易,但我正在尝试找出如何在reg表达式之间删除。与我正在编写的技术报告不同,我写了一个更有趣的例子: 当前文本: cactus in the desert blooms @year round and almost all cactus plants have very sharp needles ------ that may hurt you if you get too close----- so stay away from the needles all @

编码删除整行代码很容易,但我正在尝试找出如何在reg表达式之间删除。与我正在编写的技术报告不同,我写了一个更有趣的例子:

当前文本:

 cactus in the desert blooms @year round
 and almost all cactus plants have very sharp needles
 ------ that may hurt you if you get too close-----
 so stay away from the needles all @year and admire the 
     many colors in the buds @and flowers

 more data more data more data

 cactus in the desert blooms @year round
 and almost all cactus plants have very sharp needles
 so stay away from the needles all @year and admire the 
 data more data more data @year
 data more data more data more data @year
     many colors in the buds @and flowers
more data
 cactus in the desert blooms @year round
 and almost all cactus plants have very sharp needles
    so stay away from the needles all @year and admire the 
     many colors in the buds @and flowers

more data more data
more data more data
more data more data
在本例中,我使用@year作为初始reg表达式,使用@and作为第二个表达式。我想删除reg表达式之间的部分行和完整行。更喜欢使用SED

注意:@year的任何后续实例都需要忽略,直到找到@and为止。如果找到多个@and实例,则不应执行任何操作,因为之前没有@year实例

所示所有示例的结果:

 cactus in the desert blooms and flowers

 more data more data more data

 cactus in the desert blooms and flowers
 more data more data more data

 cactus in the desert blooms and flowers
 more data
 cactus in the desert blooms and flowers

 more data more data
 more data more data
 more data more data
使用名为cactus的文件,您可以执行以下操作:

$ sed ':a; N; s/\n/ /; ta' cactus | sed 's/[@][^@][^@]*[@]//'
 cactus in the desert blooms and flowers
cactus之前的前导“”仍然保留,如果愿意,可以删除它

在第二个表达式上使用扩展正则表达式,它将简化为:

sed ':a; N; s/\n/ /; ta' cactus | sed -E 's/@[^@]+@//'

请您尝试以下内容,完全基于您在GNU awk中展示的样本。 如果输入文件中没有任何空行,请尝试

awk -v RS= '{sub(/@year.*@and/,"and")} 1' Input_file
如图所示,输出将为:

 cactus in the desert blooms and flowers
使用Perl

$ cat ranch.txt
 cactus in the desert blooms @year round
 and almost all cactus plants have very sharp needles
 ------ that may hurt you if you get too close-----
 so stay away from the needles and admire the
     many colors in the buds @and flowers
$ perl -0777 -pe ' s/(?:\@year)(.+)(?:\@and)/and/gms ' ranch.txt
 cactus in the desert blooms and flowers
$

假设每行中最多有一个@,我将按以下方式使用GNU AWK,让file.txt内容为:

 cactus in the desert blooms @year round
 and almost all cactus plants have very sharp needles
 ------ that may hurt you if you get too close-----
 so stay away from the needles and admire the 
     many colors in the buds @and flowers
然后

说明:我将字段分隔符设置为@,将记录分隔符输出为nothing空字符串,并将doprint设置为true。然后,对于不超过1个字段的每一行,即如果doprint为真,没有@i,只打印它;对于超过1个字段的每一行,即持有@i否定doprint,则如果设置为真,则打印@else之前的内容。

并且使用awk:


这可能适用于GNU sed:

sed ':a;/@year/{:b;/@and/!{N;bb};s/\n//g;s/@year/\n/;s/@and/\nand/;s/\n.*\n//;ba}' file
在包含@year和@and的图案空间中收集线条

删除集合中的所有换行符

将@year替换为\n和@,并替换为\n和

删除引入的换行符之间的所有内容

重复一遍

注意:这将在同一行上提供两组或多组起始和结束分隔符。

使用GNU表示-z时:

$ sed -z 's/@year.*@and/and/' file
 cactus in the desert blooms and flowers

是的,这看起来也不错。sub很贪婪,可能一次就吸收了多篇文章。@kvantour,同意,但这就是为什么我按照显示的样本编写了文章,如果OP附带了一些样本/示例,需要在这篇文章中添加其他内容,那么将编辑答案。@kvantour,我已经为OP留下了关于这篇文章的评论,让我们看看OP是怎么说的。and you show是指@and吗?或者不管两个regexp@year和@and,它都应该是一个文本。如果regexp是@year和@limit,那么它是否仍然存在,或者它是否会成为limit?请告诉我们您是否可以多次出现@and?如果是,那么您希望匹配到它的最后一次出现还是它的任何特定实例?或者,您的实际输入文件中是否只有这些精确的行?请确认一下。您的示例和文本要求中缺少了此类问题的所有常用用例,例如,如何处理@年之前的2@年和@年之后的2@和@年,一个@年之前没有@年,一个@年之后没有@和,等等。因此,您正在为您展示的“一个阳光明媚的日子”案例获取解决方案-在您的输入中始终存在单个@年和@和对。如果这不是你所需要的,那么你的问题将澄清你的需求,并提供更现实的示例输入/输出。你也得到了假设@not出现在你的输入中的任何其他地方的解决方案,因为它不在你发布的示例中。如果这是一个错误的假设,那么您的示例将再次包含更多的@s以及@year或@and可以显示为子字符串的情况,如joe@andoverplumbers.com等。该文件包含自然出现的@符号,但我使用SED将这些符号替换为一个空格。我将在@year和@and中交换。Regexp@and肯定是一致的。但是,由于插入@year需要进行交换,因此它可能会在@year之前的不同行中多次出现,并出现在文件中。所以搜索需要在第一次找到@year时打开,然后在找到@and后关闭。我将把这个添加到我的例子中。如果你问题中的例子没有涵盖你的所有用例,那么编辑你的问题以显示更真实的例子。另外,不要在注释中添加文本要求-您的问题要包含所有相关信息。不要忘了提及。*是贪婪的,因此如果文件中有两组或两组以上的@year thru@和,此解决方案将删除第一个@year和最后一个@and之间的所有内容。我没有忘记,我在问题下方评论说,问题中缺少许多潜在的用例,因此OP只是得到了适用于所示的“一个阳光灿烂的日子”案例的解决方案。例如,您的答案假设OP想要删除@year和first@之间的文本,然后删除。也许他们想从第一年删除到最后一年,或者其他什么。我们只是不知道是什么
在OP,除了问题中的一个晴朗的日子,他想做任何事情。这非常接近。当只找到@和时,它就通过了箱子,这很好。当它找到两个regexp并采取行动时,它确实删除了中间的行和部分行,但是下面还有几行是空行,空行下面的所有行也都被删除了。当我离开时,作为文字,它没有删除文件的其余部分,因此,将其更改为类似于regexp是我不理解的,但是部分行没有被删除。当@year出现在下一行的另一个@year之后,然后@and出现时,它没有删除从@year的第一个实例到@and的所有内容。所有发布的解决方案都是为了与您展示的示例一起使用,仅此而已。你不应该指望他们中的任何一个人会处理你没有展示的任何东西。听起来你确实有所有常用的用例来考虑我在你的问题下的评论,所以请描述你希望他们如何处理,并在你的问题中包含这些例子,如果你想要一个处理你想要处理的每一个案例的解决方案,但是在定界符之前和之后的这个文件的变化行不会变紧吗?根据需要缩小搜索范围。只需将删除更改为,例如“s/@year[^@]+@和/和/”即可将删除限制在@year和@之间,并用和替换。对于BRE,即sed的/@year[^@][^@]*@和/和/,此命令似乎只是将文件中的每一行都替换为“and”。对不起。输入数据已更改!使用gnu awk测试的代码仅针对以前的输入数据。
awk 'BEGIN{FS="@";ORS=""} /@year/ {print $1} /@and/{print $2"\n"}' file
cactus in the desert blooms and flowers
sed ':a;/@year/{:b;/@and/!{N;bb};s/\n//g;s/@year/\n/;s/@and/\nand/;s/\n.*\n//;ba}' file
$ sed -z 's/@year.*@and/and/' file
 cactus in the desert blooms and flowers