如何使用sed命令或awk命令打印两个模式之间匹配的行,但是在文件中多次存在第二个模式?

时间:2018-04-19 06:30:48

标签: bash shell unix awk sed

我有这个输入文件F1:

Good morning!
Have a nice day;
see you again the next day;
Bye;

我想在" Have"之间打印线条。和" day"。 我试过这个命令:*sed -n '/Have/,/day/ p*' F1  输出是:祝你有个愉快的一天 但是我想要打印第二行,因为它也具有相同的模式" day"。 期望的输出: 祝你有愉快的一天; 第二天再次见到你;

任何人都可以帮我吗? 提前谢谢。

3 个答案:

答案 0 :(得分:0)

这可能适合你(GNU sed):

sed  '/Have/{:a;x;s/^\(.*\n.*day[^\n]*\).*/\1/p;x;h;d};H;$!d;ba' file

命令/Have/,/day/收集Haveday之间的最短行数,您需要的时间最长?如果是这样的话就是这样的解决方案。

在第一行中包含Have的保留空间中存储行,然后在每次出现单词Have时删除上一个集合的最后day之后的行并打印他们。在文件结尾处重复这一次。

N.B。如果没有遇到包含/Have/,/day/的行,则命令Have将收集从包含day的第一行到文件结尾的所有行。只有满足两个条件时才会打印上述解决方案。

答案 1 :(得分:0)

这应该适用于awk。基本上,它会进行2次传递 - 这就是F1在命令末尾出现两次作为要处理的文件的原因。

在第一次传递(FNR == NR)时,它会将行号保存在第一次出现的“有”的s(开始)中,并将最后一次出现的行号保存在{{ 1}}(结束)“天”这个词。

在第二遍(FNR!= NR)上,它会在es之间打印行(开始和结束)。

e

答案 2 :(得分:0)

以下将单向进行

awk '/Have/           { p=1 }
     /day/  && (p==1) { p=2; print; next }
     !/day/ && (p==2) { p = 0 }
     p' <file>

我们在这里做的是跟踪标签p。如果找到Have,请设置p=1,如果找到day,请设置p=2,同时打印并移至下一行。如果p>1表示我们找到day,如果该行不包含day,则将打印标签设置为零,否则打印。

输出

Have a nice day;
see you again the next day;

这将打印块,直到最后day

表格的输入

Good morning!
Have a nice day;
see you again the next day;
Bye;

Good morning!
Have a nice day;
see you again the next day;
Bye;

将输出:

Have a nice day;
see you again the next day;
Have a nice day;
see you again the next day;