grep 一个模式和 return 另一个特定字符前后的所有字符 bash
grep a pattern and return all characters before and after another specific character bash
我有兴趣在日志文件中搜索变量,以防搜索 returns 什么然后我希望在变量之前的所有条目,直到遇到字符 '{' 和模式之后直到遇到字符'}'。
为了更准确,让我们来看下面的例子:
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 上找东西。我只能想出用于查找模式的选项,然后 return 所有行,直到满足 '}',但是我找不到适合模式之前的行的解决方案。
我在 Perl 中找到了一个可以使用的正则表达式,但我无法使用该变量,如果我用 'foo' 切换变量,那么我将有输出。
grep -Poz '.*(?s)\{[^}]*name\tfoo.*?\}'
正则表达式非常简单,一旦将整个文件读入变量
use warnings;
use strict;
use feature 'say';
die "Usage: [=10=] filename\n" if not @ARGV;
my $file_content = do { local $/; <> }; # "slurp" file with given name
my $target = qr{name foo};
while ( $file_content =~ /({ .*? $target .*? })/gsx ) {
say ;
}
因为我们 undef
-ine input record separator inside the do block using local, the following read via the null filehandle <>
一次拉取整个文件,作为一个字符串(“slurps”它)。它由 do
块返回并分配给变量。 <>
从名称在 @ARGV
中的文件中读取,因此在程序调用时在命令行上提交了什么。
在正则表达式模式中,?
量词使 .*
仅匹配下一个子模式的第一次出现,因此在 {
之后 .*?
匹配到第一个 $target
,然后匹配(评估的)$target
,然后 .*?
匹配直到第一个 }
的所有内容。所有通过包含 ()
捕获的内容因此稍后在 </code>.</p> 中可用
<p> <code>/s
修饰符使 .
匹配换行符,它通常不会匹配换行符,这是匹配涉及多行的模式所必需的。使用 /g
修饰符,它会不断遍历内容。 /x
空格不匹配,因此我们可以展开模式以提高可读性。
$target
使用 qr 运算符编译为正确的正则表达式模式。
参见正则表达式教程 perlretut, and then there's the full reference perlre。
这是一个 Awk 尝试,试图从字里行间中读出实际需求。我猜你想说的是“如果有左大括号,打印它和右大括号之间的所有内容,以防大括号内匹配。否则,只打印匹配的行。”
我们通过在 Awk 中创建一个状态变量来实现这一点,该变量跟踪您是否处于大括号上下文中。这个简单的实现不会正确处理嵌套的大括号;如果那是你的要求,也许 post 一个新的更好的问题与你的 实际 要求。
awk -v search="foo" 'n { context[++n] = [=10=] }
/{/ { delete context; n=0; matched=0; context[++n] = [=10=] }
/}/ && n { if (matched) for (i=1; i<=n; i++) print context[i];
delete context; n=0 }
[=10=] ~ search { if(n) matched=1; else print }' file
变量n
为采集数组的行数context
;当它为零时,我们不在大括号之间的上下文中。如果我们找到一个匹配项并将行收集到 context
,则推迟打印直到我们收集了整个 context
。否则,只打印当前行。
我有兴趣在日志文件中搜索变量,以防搜索 returns 什么然后我希望在变量之前的所有条目,直到遇到字符 '{' 和模式之后直到遇到字符'}'。
为了更准确,让我们来看下面的例子:
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 上找东西。我只能想出用于查找模式的选项,然后 return 所有行,直到满足 '}',但是我找不到适合模式之前的行的解决方案。
我在 Perl 中找到了一个可以使用的正则表达式,但我无法使用该变量,如果我用 'foo' 切换变量,那么我将有输出。
grep -Poz '.*(?s)\{[^}]*name\tfoo.*?\}'
正则表达式非常简单,一旦将整个文件读入变量
use warnings;
use strict;
use feature 'say';
die "Usage: [=10=] filename\n" if not @ARGV;
my $file_content = do { local $/; <> }; # "slurp" file with given name
my $target = qr{name foo};
while ( $file_content =~ /({ .*? $target .*? })/gsx ) {
say ;
}
因为我们 undef
-ine input record separator inside the do block using local, the following read via the null filehandle <>
一次拉取整个文件,作为一个字符串(“slurps”它)。它由 do
块返回并分配给变量。 <>
从名称在 @ARGV
中的文件中读取,因此在程序调用时在命令行上提交了什么。
在正则表达式模式中,?
量词使 .*
仅匹配下一个子模式的第一次出现,因此在 {
之后 .*?
匹配到第一个 $target
,然后匹配(评估的)$target
,然后 .*?
匹配直到第一个 }
的所有内容。所有通过包含 ()
捕获的内容因此稍后在 </code>.</p> 中可用
<p> <code>/s
修饰符使 .
匹配换行符,它通常不会匹配换行符,这是匹配涉及多行的模式所必需的。使用 /g
修饰符,它会不断遍历内容。 /x
空格不匹配,因此我们可以展开模式以提高可读性。
$target
使用 qr 运算符编译为正确的正则表达式模式。
参见正则表达式教程 perlretut, and then there's the full reference perlre。
这是一个 Awk 尝试,试图从字里行间中读出实际需求。我猜你想说的是“如果有左大括号,打印它和右大括号之间的所有内容,以防大括号内匹配。否则,只打印匹配的行。”
我们通过在 Awk 中创建一个状态变量来实现这一点,该变量跟踪您是否处于大括号上下文中。这个简单的实现不会正确处理嵌套的大括号;如果那是你的要求,也许 post 一个新的更好的问题与你的 实际 要求。
awk -v search="foo" 'n { context[++n] = [=10=] }
/{/ { delete context; n=0; matched=0; context[++n] = [=10=] }
/}/ && n { if (matched) for (i=1; i<=n; i++) print context[i];
delete context; n=0 }
[=10=] ~ search { if(n) matched=1; else print }' file
变量n
为采集数组的行数context
;当它为零时,我们不在大括号之间的上下文中。如果我们找到一个匹配项并将行收集到 context
,则推迟打印直到我们收集了整个 context
。否则,只打印当前行。