Bash grep表示单词,如果匹配,则获取括号之间的内容

Bash grep表示单词,如果匹配,则获取括号之间的内容,bash,sed,grep,Bash,Sed,Grep,我有许多文件,通常如下所示 { key1:value1, key2:value4 }, { key1:value1, key2:value4 }, { key3:value3, key5:value5 } 我想找一把钥匙,比如说钥匙5。如果存在键5,则我 希望打印括号下的所有内容。在这种情况下,它将是 { key3:valu

我有许多文件,通常如下所示

    { 
      key1:value1, 
      key2:value4 
    }, 
    { 
       key1:value1, 
       key2:value4 
    }, 
    { 
       key3:value3,
       key5:value5 
    }
我想找一把钥匙,比如说钥匙5。如果存在键5,则我 希望打印括号下的所有内容。在这种情况下,它将是

    { 
       key3:value3,
       key5:value5 
    }

我不想使用grep在上下文之后和上下文之前进行操作,因为括号中的键可能会有所不同。括号内的内容不在一行中。

您可以使用gnu awk和自定义记录分隔符:

awk -v RS='{[^}]+}' 'RT ~ /key5/ {print RT}' file
{
   key3:value3,
   key5:value5
}
RT
RS
模式表示匹配的文本

另一种方法是使用gnu grep:

grep -zoP '{[^}]*?key5[^}]*}' file
{
   key3:value3,
   key5:value5
}
编辑:您还可以使用
perl

perl -0ne 'print $1  . "\n"if /({[^}]*?key5[^}]*})/' file
{
   key3:value3,
   key5:value5
}

编辑2:以下是BSD awk解决方案:

awk -v RS='{' '/key5/{printf "%s", RS $0}' file
{
   key3:value3,
   key5:value5
}
sed -n 'H;/{/h;/}/{g;/key5/p}' file

您已经有了答案,但只是为了好玩,有一个
sed
解决方案:

awk -v RS='{' '/key5/{printf "%s", RS $0}' file
{
   key3:value3,
   key5:value5
}
sed -n 'H;/{/h;/}/{g;/key5/p}' file
  • 将当前行追加到H旧空格
  • 如果行与
    /{/
    匹配,则用它替换h旧空格的内容
  • 如果行匹配
    /}/
    g设置保留空间,替换当前行。如果替换匹配
    /key5/
    p打印它(打印保留空间中累积的所有内容,从开始
    {
    到结束
    }
  • 除非明确打印,否则不要输出该行(
    -n
    标志)
与任何使用保留空间的
sed
脚本一样,您最好使用
awk
解决方案:)

这可能适合您(GNU-sed):

如果一行包含
{
请将保留空间替换为该行。否则,请将该行附加到保留空间。删除除包含
}
的行以外的所有行。在这种情况下,请切换到保留空间,并在存在所需字符串的情况下打印该行


注意,
-N
开关调用seds grep-like-nature并抑制每行的正常打印输出。

我正在Mac上尝试这些命令,这些命令似乎不起作用。GNU命令也是BASH,但OSX默认情况下不提供它们。无论如何,perl应该在OSX上工作,因为除非使用循环,否则BSD命令不会跨多行搜索。请检查我的更新答案以获得BSD(OSX)awk解决方案。如果这是JSON,您应该将其视为JSON,而不是与我兼容的textLooks POSIX。是什么让它成为GNU?