0

当“成功”时,我的命令输出采用以下形式:

/ >  -------
ABC123
/ > 

但是,此命令可能会发出类似这样的信息(“失败”):

/ >  -------
ABC123
 -------
DEF456
 -------
Hello (world!)
 -------
(any old string, really)
/ > 

或者,这个(另一个“失败”):

/ > / >

对于第一个示例,我想发出:

ABC123

对于其他两个示例,我想发出空字符串。

我试过这个,这对第三个例子很有用:

mycmd | pcregrep -M '(?:/\s>\s{2}-{7}\n)[^\n]*(?!\n.*\n)'

但是对于它发出的前两个示例:

/ >  -------
ABC123

我不知道该怎么办。我上面的正则表达式是尝试匹配前导/ > -------但不捕获它,然后仅在下一行后面没有以换行符结尾的另一行时才匹配。除了解决这个问题,我还可以使用其他东西pcregrep,但我无法用awkor来表达这一点sed。我会使用 Python,但它对我的需要来说太慢了。有什么帮助吗?

4

3 回答 3

1

我认为以下内容会起作用,但如果它包含换行符,我无法让后向表达式起作用。

mycmd | pcregrep -M '(?<=^/ >  -{7}\n).*\n(?=/ > $)'

但是以下两阶段解决方案对我有用:

mycmd | pcregrep -M '^/ >  -{7}\n.*\n/ > $' | pcregrep -v '^/ >'

更新以响应 OP 的回答

我喜欢 \K 转义:-)

我假设您不想匹配以下情况

/ > -------
/ > perhaps text here
/ > 

当它包含 \n 时,即使它嵌入在积极的前瞻中,我也能够获得消极的前瞻工作。

这是一个更简单的正则表达式,\K它更接近您想要的。它不允许 . 之后的任何内容/ >,但它仍然允许 . 之前的行/ > -------

mycmd | pcregrep -Mo '^/ >  -{7}\n\K(?!/ >).+(?=\n/ > $(?!\n[\s\S]))'

如果应该允许捕获的行以 开头/ >,那么它更简单:

mycmd | pcregrep -Mo '^/ >  -{7}\n\K.+(?=\n/ > $(?!\n[\s\S]))'

最终更新

这是一个 sed one 衬里,我相信它给出了确切的结果,不允许在之前或之后有任何额外的行。但是,它确实允许捕获以 开头的行/ >

mycmd | sed -n '1{/^\/ >  -\{7\}$/{n;/./{h;n;/^\/ > $/{${x;p}}}}}'

这是另一个 sed 解决方案

mycmd | sed -n '1{h;n;H;x;N;${/^\/ >  -\{7\}\n..*\n\/ > $/{x;p}}}'
于 2014-05-08T16:06:14.517 回答
1

pcregrep实际上,我使用以下命令取得了成功(在咬牙切齿之后) :

pcregrep -Mo '^/ > {2}-{7}[\n\r]\K[^\n\r]+(?=[\n\r]/ > $)'

没有-o标志,它包括第一行(尽管使用\K)。-o使得pcregrep只发出与模式匹配的行。事实证明,在尝试匹配换行符时,负前瞻似乎不适用于多行模式。此外,在多行模式下,\s将匹配换行符,所以我停止使用它。

我确实想指出,这个解决方案和 dbenham 的解决方案都不是我想要的。我希望检查在第二行之后除了最后一行(即不包含另一个换行符)之外没有任何其他行。这些解决方案假设更多关于输出如何结束,但这是必须的。

于 2014-05-08T16:37:40.103 回答
1

您还可以使用 awk:

BEGIN {
   first_line = "";
   second_line = "";
   third_line = "";

   ctr = 0;
}
{
   if (ctr == 0 ){
      first_line = $0;
   } else if (ctr == 1) {
      second_line = $0;
   } else if (ctr == 2 ) {
      third_line = $0;
   }
   ctr++;
}
END {
   if( first_line ~ /\/ >  -------/){
      if( third_line ~ /\/ >/){
         print second_line;
      }
   }
}

输出:

$ echo "/ >  -------\nABC12\n ---\n/ >\n" | awk -f test.awk
$ echo "/ >  -------\nABC12\n/ >\n" | awk -f test.awk
ABC12
$

我敢肯定 awk 专家会畏缩,但它很快并且完成了工作。

于 2014-05-08T13:49:34.513 回答