打印shell中两个模式之间的所有行

时间:2017-08-22 07:33:45

标签: shell pattern-matching

我有一个文件,它是在每日cronjob中运行的脚本的日志。日志文件看起来像 -

Aug 19

Line1
Line2
Line3
Line4
Line5
Line6
Line7
Line8
Line9

Aug 19

Aug 20

Line1
Line2
Line3
Line4
Line5
Line6
Line7
Line8
Line9

Aug 20

Aug 21

Line1
Line2
Line3
Line4
Line5
Line6
Line7
Line8
Line9

Aug 21

日志由脚本编写,从日期开始,以日期结束,并在所有日志之间写入。

现在,当我尝试使用以下命令获取一天的日志时 -

sed -n '/Aug 19/,/Aug 19/p' filename

它将输出显示为 -

Aug 19

Line1
Line2
Line3
Line4
Line5
Line6
Line7
Line8
Line9

Aug 19

但是如果我尝试获取多个日期的日志,则总是会丢失最后一天的日志。

示例 - 如果我运行命令

sed -n '/Aug 19/,/Aug 20/p' filename

输出看起来像 -

Aug 19

Line1
Line2
Line3
Line4
Line5
Line6
Line7
Line8
Line9

Aug 19

Aug 20

我已经浏览了这个网站并找到了类似问题的一些有价值的输入,但没有一个解决方案适合我。链接为Link 1

Link 2

我尝试的命令是 -

awk '/Aug 15/{a=1}/Aug 21/{print;a=0}a'
awk '/Aug 15/,/Aug 21/'
sed -n '/Aug 15/,/Aug 21/p
grep -Pzo "(?s)(Aug 15(.*?)(Aug 21|\Z))"

但是没有一个命令给出最后日期的日志,所有命令都打印到第一个时间戳,如上所示。

4 个答案:

答案 0 :(得分:0)

您可以使用分号分隔多个模式。

sed -n '/Aug 19/,/Aug 19/p;/Aug 20/,/Aug 20/p' filename

答案 1 :(得分:0)

我认为您可以使用awk命令来打印Aug 19&之间的行。 Aug 20

awk '/Aug 19/||/Aug 20/{a++}a; a==4{a=0}' file

简要说明,

  • /Aug 19/||/Aug 20/:找到与Aug 19Aug 20
  • 匹配的记录
  • 如果符合条件,请设置标记a++
  • 如果分号前面的标记a大于0,则会打印记录。
  • 最终条件,如果a==4,则重置a=0,请注意,如果Aug 19Aug 20超过4,则仅适用于示例中的案例,修改答案中的数字4以满足您的新要求。

如果要将搜索到的模式分配到变量中,请按照以下步骤修改命令

$ b="Aug 19"
$ c="Aug 20"
$ awk -v b="$b" -v c="$c" '$0 ~ c||$0 ~ b{a++}a; a==4{a=0}' file

答案 2 :(得分:0)

你能不能一次尝试关注awk解决方案,让我知道这是否对你有帮助。

awk '/Aug 19/||/Aug 20/{flag=1}; /Aug/ && (!/Aug 19/ && !/Aug 20/){flag=""} flag'  Input_file

编辑:此处也添加输出以让OP知道。

awk '/Aug 19/||/Aug 20/{flag=1}; /Aug/ && (!/Aug 19/ && !/Aug 20/){flag=""} flag' Input_file
Aug 19

Line1
Line2
Line3
Line4
Line5
Line6
Line7
Line8
Line9

Aug 19

Aug 20

Line1
Line2
Line3
Line4
Line5
Line6
Line7
Line8
Line9

Aug 20

答案 3 :(得分:0)

以下方法在概念上很容易理解......

  • 将所有行从8月19日开始打印到文件末尾。
  • 反转行的顺序(使用tac,因为tac向后cat
  • 从8月21日开始打印所有行。
  • 将行的顺序反转回原始顺序。
sed -ne '/Aug 19/,$p' filename | tac | sed -ne '/Aug 21/,$p' | tac