正则表达式向后查找字符串和第一次出现的另一个字符串之间的所有文本

时间:2015-05-15 02:15:59

标签: regex bash awk

我需要在'错误:'之前找到最近出现的'GET'(GET zzzz)并捕获其中的所有文本。

GET xxxxx
GET yyyyy
GET zzzzz
Some text
more text
error: this is an error

可以这样做吗?

修改

谢谢,awk解决方案有效,但是通过最后出现'错误:'可以进一步改善吗?

GET xxxxx
GET yyyyy
GET zzzzz
Some text
more text
error: this is the first error

GET xxxxx
GET yyyyy
GET zzzzz
Some text
more text
error: this is the last error

3 个答案:

答案 0 :(得分:3)

尝试以下awk解决方案:

awk '
  /^GET/ { delete lines; c=0; inBlock=1 }
  /^error:/ { for(i=1; i<=c; ++i) print lines[i]; print; exit }
  inBlock { lines[++c] = $0 }
' file

这假定只打印 1 块,并且还应打印error:行。 (更新:请参阅下面的解决方案,仅打印最后块)。

  • /^GET/ { delete lines; c=0; inBlock=1 }开始在变量lines中构建一系列行,只要在行的开头遇到字符串GET
  • /^error:/ { for(i=1; i<=c; ++i) print lines[i]; print; exit }在该行的开头匹配字符串error:,并打印出目前为止构建的所有行,然后是当前行,然后退出。
  • inBlock { lines[++c] = $0 }将以最新GET行开头的每一行添加到数组中。
根据OP的要求

更新

要报告(仅)以error:结尾的 last 块,请使用以下命令:

awk '
  /^GET/ { delete lines; c=0; inBlock=1 }
  inBlock { lines[++c] = $0 }
  /^error:/ { inBlock=0; }
  END { for(i=1; i<=c; ++i) print lines[i] }
' file

这与第一个解决方案的不同之处在于,后面的块只是简单地替换了之前的块,以便最后一个块“wins”,然后在Awk脚本的END块中处理完所有输入后打印

答案 1 :(得分:1)

假设:

$ echo "$tgt"
first line
second line
GET xxxxx
GET yyyyy
GET zzzzz
Some text
more text
error: this is the first error

GET xxxxx
GET yyyyy
GET zzzzzLAST
Some text
more text
error: this is the last error
last line

你可以有一个多行正则表达式,它将丢弃所有字符,直到最后一个所需的块,如下所示:

/^.*^(GET.*^error[^\n]*)/ms

Demo

现在使用Perl,读取整个文件并与之匹配。 -0777命令行选项将导致读取整个文件:

$ echo "$tgt" | perl -0777 -ne 'print $1 if m/^.*^(GET.*^error[^\n]*)/sm'
GET zzzzzLAST
Some text
more text
error: this is the last error

如果要包含超出最后一个“错误”行的行,请将正则表达式更改为:

/\A.*^(GET.*^error.*)\Z/ms

Demo

Perl:

$ echo "$tgt" | perl -0777 -ne 'print $1 if m/\A.*^(GET.*^error.*)\Z/ms'
GET zzzzzLAST
Some text
more text
error: this is the last error
last line

答案 2 :(得分:-1)

我设法通过以下regexp得到了理想的结果:

(GET[^\n]+\n(?!GET).*)error:

您可以在http://regexpal.com/中进行测试。“匹配所有”模式。