打印第一个匹配括号之间的内容

打印第一个匹配括号之间的内容

输入示例:

START{
    some text

    {
      more text}
almost there
}
nothing important{
...

期望的输出:

START{
    some text

    {
      more text}
almost there
}

第一个左括号可以位于不同的位置:

START{...
START {...
START
{...

开始还可以包含特殊字符,例如:*

我想打印出所有内容,包括从 START 开始的内容以及第一次匹配之间的所有内容{}(在 bash 中)。我正在考虑有一个计数器,当它找到时增加{并在找到时减少}。当结果为零时,它将停止打印(大括号始终匹配)。

答案1

一种简单的暴力方法,可以在所有 Unix 机器上的任何 shell 中的任何 awk 中工作:

$ cat tst.awk
s=index($0,"START") { $0=substr($0,s); f=1 }
f { rec = rec $0 RS }
END {
    len = length(rec)
    for (i=1; i<=len; i++) {
        char = substr(rec,i,1)
        if ( char == "{" ) {
            ++cnt
        }
        else if ( char == "}" ) {
            if ( --cnt == 0 ) {
                print substr(rec,1,i)
                exit
            }
        }
    }
}

$ awk -f tst.awk file
START{
    some text

    {
      more text}
almost there
}

答案2

pcregrep

start_word='START'
pcregrep -Mo "(?s)\Q$start_word\E\h*(\{(?:[^{}]++|(?1))*+\})" < your-file

使用zsh内置函数:

set -o rematchpcre
start_word='START'
[[ $(<your-file) =~ "(?s)\Q$start_word\E\h*(\{(?:[^{}]++|(?1))*+\})" ]] &&
  print -r -- $MATCH

它们使用 PCRE 的递归正则表达式功能,上面(?1)回顾了第一(...)对中的正则表达式。

如果你既没有pcregrep也没有zsh,您可以随时求助于真实的事情( PCRE 中perlP):

perl -l -0777 -sne '
    print $& if /\Q$start_word\E\h*(\{(?:[^{}]++|(?1))*+\})/s
  ' -- -start_word='START' < your-file

(请注意,除了其中perl一个之外,所有其他都假设$start_word不包含\E)。

相关内容