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 的情况下失败。如何做。
$ 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)
那些 (pcregrep
和grep -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
它在内存中吸食整个文件一样)。