grep一个模式,并返回另一个特定字符bash前后的所有字符



我有兴趣在日志文件中搜索一个变量,如果搜索返回一些东西,那么我希望在变量之前找到所有条目,直到字符"{"出现,在模式之后找到字符"}"出现。

更准确地说,让我们举以下例子:

something something {
entry 1
entry 2
name foo
entry 3
entry 4
}
something something test
test1 test2
test3 test4

在这种情况下,我会搜索"name foo",它将存储在一个变量中(我之前在一个单独的部分中创建(,预期的输出将是:

{
entry 1
entry 2
name foo
entry 3
entry 4
}

我试着在grep、awk或sed上找到一些东西。我只能想出找到图案的选项,然后返回所有线条,直到满足"}",但我找不到适合图案之前线条的解决方案。

我在Perl中找到了一个可以使用的正则表达式,但我不能使用该变量,如果我用"foo"切换变量,那么我就会有输出。

grep -Poz '.*(?s){[^}]*nametfoo.*?}'

正则表达式非常简单,一旦将整个文件读取到变量中

use warnings;
use strict; 
use feature 'say';
die "Usage: $0 filenamen" if not @ARGV;
my $file_content = do { local $/; <> };  # "slurp" file with given name
my $target = qr{name foo};
while ( $file_content =~ /({ .*? $target .*? })/gsx ) { 
say $1; 
}

由于我们使用local将输入记录分隔符undef放入do块中,因此下面通过null文件句柄<>读取的内容会一次将整个文件作为字符串("slurps"it(。它由do块返回并分配给变量。<>从名为@ARGV的文件中读取,因此在程序调用时在命令行上提交了什么。

在正则表达式模式中,?量词使.*只匹配到下一个子模式的第一次出现,因此在{之后,.*?匹配到第一个(评估的($target,然后匹配$target,然后.*?每一次匹配直到第一个}。所有这些都是通过封装()来捕获的,因此稍后在$1中可用。

/s修饰符使.匹配换行符,它通常不匹配换行符的内容,以及匹配跨多行的模式所必需的内容。使用/g修饰符,它会不断遍历字符串,搜索所有这样的匹配项。有了/x,空白是不匹配的,所以为了可读性,我们可以展开模式(甚至是在行上——并使用注释!(。

使用qr运算符将$target编译为正确的正则表达式模式。

请参阅regex教程perlreput,然后是完整的perlre参考。

这里有一个Awk尝试,它试图在行与行之间进行读取,以阐明实际的需求。我猜你想说的是";如果有一个左大括号,请打印它和右大括号之间的所有内容,以防大括号内匹配。否则,只需打印匹配的行">

我们通过在Awk中创建一个状态变量来实现这一点,该变量可以跟踪您是否处于大括号上下文中。这种简单的实现无法正确处理嵌套的大括号;如果这是您的要求,也许可以发布一个新的、更好的问题,说明您的实际要求。

awk -v search="foo" 'n { context[++n] = $0 }
/{/ { delete context; n=0; matched=0; context[++n] = $0 }
/}/ && n { if (matched) for (i=1; i<=n; i++) print context[i];
delete context; n=0 }
$0 ~ search { if(n) matched=1; else print }' file

变量CCD_ 21是所收集的阵列CCD_;当它为零时,我们不在大括号之间的上下文中。如果我们找到匹配项并将行收集到context中,则推迟打印,直到我们收集了整个context。否则,只打印当前行。

最新更新