简体   繁体   English

如何在包含特定搜索字符串的两个大括号之间获得多行字符串?

[英]How do I get multi-line string between two braces containing a specific search string?

I'm looking for a quick and easy one-liner to extract all brace-delimited text-blocks containing a search string from a text file. 我正在寻找一个快速简单的单行程序来提取包含来自文本文件的搜索字符串的所有大括号分隔的文本块。 I've just about googled myself crazy on this, but everyone seems to be only posting about getting the text between braces without a search string. 我只是在谷歌搜索自己疯狂,但每个人似乎只发布关于在没有搜索字符串的情况下在大括号之间获取文本。

I've got a large text file with contents like this: 我有一个包含这样内容的大文本文件:

blabla
blabla {
  blabla
}
blabla
blabla {
  blabla
  blablaeventblabla
}
blabla

The vast majority of bracketed entries do not contain the search string, which is "event". 绝大多数括号内的条目不包含搜索字符串,即“事件”。

What I am trying to extract are all text (especially including multi-line matches) between each set of curly braces, but only if said text also contains the search string. 我想要提取的是每组花括号之间的所有文本(特别是包括多行匹配),但前提是所述文本还包含搜索字符串。 So output like this: 所以输出如下:

blabla {
  blabla
  blablaeventblabla
}

My linux command line is /usr/bin/bash. 我的linux命令行是/ usr / bin / bash。 I've been trying various grep and awk commands, but just can't get it to work: 我一直在尝试各种grep和awk命令,但是无法让它工作:

awk '/{/,/event/,/}/' filepath

grep -iE "/{.*event.*/}" filepath

I was thinking this would be really easy, as it's a common task. 我觉得这很容易,因为这是一项常见的任务。 What am I missing here? 我在这里错过了什么?

This gnu-awk should work: 这个gnu-awk应该有效:

awk -v RS='[^\n]*{|}' 'RT ~ /{/{p=RT} /event/{ print p $0 RT }' file
blabla {
   blabla
   blablaeventblabla
}

RS='[^\\n]*{\\n|}' sets input record separator as any text followed by { OR a } . RS='[^\\n]*{\\n|}'将输入记录分隔符设置为后跟{ OR a }任何文本。 RT is the internal awk variable that is set to matched text based on RS regex. RT是内部awk变量,根据RS正则表达式设置为匹配文本。

User 999999999999999999999999999999 had a nice answer using sed which I really liked, unfortunately their answer appears to have disappeared for some reason. 用户999999999999999999999999999999得到了一个很好的答案使用sed ,我真的很喜欢,不幸的是他们的答案似乎已经因某种原因消失了。

Here it is for those who might be interested: 这是为了那些可能感兴趣的人:

sed '/{/{:1; /}/!{N; b1}; /event/p}; d' filepath

Explanation: 说明:

/{/ if current line contains { then execute next block { start block :1; label for code to jump to /}/! if the line does not contain /{/ if current line contains { then execute next block { start block :1; label for code to jump to /}/! if the line does not contain then execute next block { start block :1; label for code to jump to /}/! if the line does not contain then execute next block { start block :1; label for code to jump to /}/! if the line does not contain } then execute next block { start block N; add next line to pattern space b1 jump to label 1 }; end block /event/p if the pattern space contains the search string, print it (at this point the pattern space contains a full block of lines from then execute next block { start block :1; label for code to jump to /}/! if the line does not contain } then execute next block { start block N; add next line to pattern space b1 jump to label 1 }; end block /event/p if the pattern space contains the search string, print it (at this point the pattern space contains a full block of lines from then execute next block { start block N; add next line to pattern space b1 jump to label 1 }; end block /event/p if the pattern space contains the search string, print it (at this point the pattern space contains a full block of lines from then execute next block { start block N; add next line to pattern space b1 jump to label 1 }; end block /event/p if the pattern space contains the search string, print it (at this point the pattern space contains a full block of lines from { to } ) }; end block d delete pattern space then execute next block { start block N; add next line to pattern space b1 jump to label 1 }; end block /event/p if the pattern space contains the search string, print it (at this point the pattern space contains a full block of lines from { to } ) }; end block d delete pattern space then execute next block { start block N; add next line to pattern space b1 jump to label 1 }; end block /event/p if the pattern space contains the search string, print it (at this point the pattern space contains a full block of lines from ) }; end block d delete pattern space ) }; end block d delete pattern space

Here is a modified version of this gem from 'leu' (10x leu for enlighten us). 这是来自'leu'的这个宝石的修改版本(10x leu用于启发我们)。 This one is doing something very similarly. 这个做的事情非常相似。 Extract everything between which begin with 'DEC::PKCS7[' and ending with ']!': 提取以'DEC :: PKCS7 ['开头并以']结尾的所有内容!':

cat file | sed '/^DEC::PKCS7\[/{s///; :1; /\]\!$/!{N; b1;}; s///;};'
Explanation:
/^DEC::PKCS7\[/             # if current line begins with 'DEC::PKCS7[' then execute next block
{                           # start block
    s///;                       # remove all upto 'DEC::PKCS7['
    :1;                         # label '1' for code to jump to
    /\]\!$/!                     # if the line does not end with ']!' then execute next block
    {                               # start block
        N;                          # add next line to pattern space
        b1;                         # jump to label 1
    };                          # end block
    s///;                       # remove all from ']!' to end of line
};                          # end block

Notes: 笔记:

  • This works on single and multi-line. 这适用于单线和多线。
  • This will have unexpected behavior if you have ']!' 如果你有'],这将有意想不到的行为! in the middle of the input. 在输入的中间。
  • This does not answer the question. 这不回答这个问题。 It's already answered very well. 它已经得到了很好的回答。 My intentions are just to help other cases. 我的意图只是为了帮助其他案件。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM