7

I have a file like this:-

pin(ABC) {  
              a b c d e f {  
              abc  
              }  
             }  
pin(XYZ) {  
              g h i j k  {  
                      j k {  
                        cg {  
                     }  
                    }  
                   }  
                  }  
abcd pqrs rstu  
mango banana tree  
pin(PQR) {  
               mango  
         }  

Now i want to grep the text like this:-
when i give ABC as input then output should be a file named ABC with the content from "pin(ABC) {" upto matching bracket "}" like this :-

pin(ABC) {  
              a b c d e f {  
              abc  
              }  
             }  

when i give PQR the output should be a file named PQR with this content:-

pin(PQR) {  
               mango  
         }  

& so on for any word which is inside pin()
one way to do it is to grep the text from "pin(ABC" till next name "pin" & direct the output to the file named "ABC" , it works for only ABC but fails for case of PQR & XYZ. How to do it.

1
  • Grep has a -A option, which can specify how many lines to show after the match - this does have the problem that you need to know how many lines that need to be shown.
    – Wilf
    Jul 31, 2014 at 13:40

1 Answer 1

7
$ pcregrep -Mo 'pin\(ABC\) (\{([^{}]++|(?1))*\})' file
pin(ABC) {
              a b c d e f {
              abc
              }
             }

If you don't have pcregrep but have GNU grep and it has been built with support for PCRE patterns and your file is not too big and doesn't contain NUL characters, you can do:

grep -zPo 'pin\(ABC\) (\{([^{}]++|(?1))*\})' file

Those (pcregrep and grep -P) are using PCRE patterns that support recursive regex operators.

pcregrep -M turns on the multiline mode (where pcregrep can pull several lines as needed while matching the regexp) and grep -z tells the records are NUL-separated instead of being lines.

The trick above is in the (?1) operator that means the regexps inside the first paren group so we have a recursive regexp: we're matching { followed by a sequence of 0 or more (*) sequences of non-brace characters ([^{}]++, ++ being the possessive version of +) or the regexp in the outer (...) again ({ followed by...).

See the man page for pcrepattern for details. That's copied almost verbatim from an example in there.

Using perl:

perl -l -0777 -ne 'print $& while /pin\(ABC\) (\{([^{}]++|(?1))*\})/g'

(like for grep it slurps the whole file in memory).

4
  • 1
    Thanks for reply, It would be better if you can explain it your answer in step by step so that i can learn your approach. Jul 31, 2014 at 13:48
  • Hi Stephane , it is not working for some words in my original file, i don't know why , Can we have any other solution.If you want the original file then i can post it but it have 21142 line & its size is 7.6M .Please reply. Aug 5, 2014 at 13:10
  • @yogendrasingh, yes paste it somewhere like on pastebin. Hard to tell what's wrong without seeing the file. Aug 5, 2014 at 13:15
  • Stephane , i have done it somehow, i just deleted all the previous lines before the search pattern , so my file became shorter. Then it works for all patterns one by one,May be the reason being because of big file.Anyways Thanks for giving your time :) Aug 5, 2014 at 17:04

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .