我有一个这样的文件:-
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
}
现在我想像这样 grep 文本:-
当我将 ABC 作为输入时,输出应该是一个名为 ABC 的文件,其内容从“pin(ABC) {”一直到匹配的括号“}”,如下所示:-
pin(ABC) {
a b c d e f {
abc
}
}
当我给出 PQR 时,输出应该是一个名为 PQR 的文件,其中包含以下内容:-
pin(PQR) {
mango
}
等等,对于 pin() 内的任何单词,
一种方法是 grep 从“pin(ABC”到下一个名称“pin”的文本,并将输出定向到名为“ABC”的文件,它仅适用于ABC 但对于 PQR 和 XYZ 的情况失败了如何做。
答案1
$ pcregrep -Mo 'pin\(ABC\) (\{([^{}]++|(?1))*\})' file
pin(ABC) {
a b c d e f {
abc
}
}
如果您没有,pcregrep
但有 GNU grep
,并且它是在支持 PCRE 模式的情况下构建的,并且您的文件不是太大且不包含 NUL 字符,您可以执行以下操作:
grep -zPo 'pin\(ABC\) (\{([^{}]++|(?1))*\})' file
这些 (pcregrep
和grep -P
) 使用支持递归正则表达式运算符的 PCRE 模式。
pcregrep -M
打开多行模式(pcregrep
在匹配正则表达式时可以根据需要拉出多行)并grep -z
告诉记录是 NUL 分隔的而不是线。
上面的技巧是在(?1)
运算符中,这意味着里面的正则表达式第一的帕伦集团所以我们有一个递归正则表达式:我们匹配{
后跟 0 个或多个 ( *
) 非大括号字符序列的序列([^{}]++
,++
是 的所有格版本+
)或者再次使用外部的正则表达式(...)
({
后面跟着...)。
pcrepattern
有关详细信息,请参阅手册页。这几乎是从那里的示例中逐字复制的。
使用perl
:
perl -l -0777 -ne 'print $& while /pin\(ABC\) (\{([^{}]++|(?1))*\})/g'
(就像grep
它吞噬内存中的整个文件一样)。