grep 最多匹配括号

yog*_*ngh 7 sed awk shell-script

我有一个这样的文件:-

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  
         }  
Run Code Online (Sandbox Code Playgroud)

现在我想像这样 grep 文本:-
当我将 ABC 作为输入时,输出应该是一个名为 ABC 的文件,其内容从“pin(ABC) {”到匹配的括号“}”,如下所示:-

pin(ABC) {  
              a b c d e f {  
              abc  
              }  
             }  
Run Code Online (Sandbox Code Playgroud)

当我给 PQR 时,输出应该是一个名为 PQR 的文件,其中包含以下内容:-

pin(PQR) {  
               mango  
         }  
Run Code Online (Sandbox Code Playgroud)

& 等等对于 pin() 内的任何单词,
一种方法是将文本从 "pin(ABC" 直到下一个名称 "pin" 进行 grep 并将输出定向到名为 "ABC" 的文件,它仅适用于ABC 但在 PQR 和 XYZ 的情况下失败。如何做。

Sté*_*las 6

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

如果你没有pcregrep但有 GNUgrep并且它支持 PCRE 模式并且你的文件不是太大并且不包含 NUL 字符,你可以这样做:

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

那些 (pcregrepgrep -P) 正在使用支持递归正则表达式运算符的 PCRE 模式。

pcregrep -M打开多行模式(在pcregrep匹配正则表达式时可以根据需要拉多行)并grep -z告诉记录是 NUL 分隔的而不是lines

上面的技巧是在(?1)运算符中,这意味着第一个括号组内的正则表达式,所以我们有一个递归正则表达式:我们匹配{后跟一个序列的 0 或多个 ( *) 非大括号字符序列([^{}]++++作为所有格版本+)外部的正则表达式(...){后跟...)。

有关pcrepattern详细信息,请参阅手册页。这几乎是从那里的一个例子中逐字复制的。

使用perl

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

(就像grep它在内存中吸食整个文件一样)。