sed 可以在定义范围的模式中进行反向引用吗?

Jac*_*ose 5 sed regular-expression

我正在尝试sed从长文件(Junos 配置)中提取像这样的大括号分隔的配置块:

                group foo {
                    command;
                    setting {
                        value;
                    }
                    command;
                }
Run Code Online (Sandbox Code Playgroud)

诀窍是停在}与第一行缩进相同的地方。

我学习了如何使用sed从一种模式匹配到另一种模式,并尝试了以下操作:

$ sed -rn '/^( *)group foo/,/^\1\}/p' config.txt
sed: -e expression #1, char 41: Invalid back reference
Run Code Online (Sandbox Code Playgroud)

问题是/^( *)group foo//^\1\}/是两个独立的模式,并且反向引用在它们之间不起作用吗?如果是这样,我怎样才能做到这一点?

Qua*_*odo 3

你是对的:虽然反向引用是在基本正则表达式(BRE) 中定义的(并且由于每个 sed 地址都是一个 BRE,所以它支持反向引用),但反向引用无法检索在另一个 BRE 中定义的捕获组。因此该地址中的捕获组/^( *)group foo/无法被其他地址检索到/^\1\}/

test.awk是通过计算左大括号和右大括号来实现的:

brk && /\{/{brk++} #Increment brk if brk is not zero and line contains {
brk && /\}/{brk--} #Decrement brk if brk is not zero and line contains }
/^[[:blank:]]*group foo \{/{brk=1;prt=1} #Set brk and prt if match initial pattern
prt                #Print line if prt is set
!brk && prt{prt=0} #If brk is zero and prt is not, set prt=0
Run Code Online (Sandbox Code Playgroud)
$ cat file
foo bar
        foo bar2
        }
                group foo {
                    command;
                    setting {
                        value;
                    }
                    command;
                }
        dri {
    }
end
$ awk -f test.awk file
                group foo {
                    command;
                    setting {
                        value;
                    }
                    command;
                }
Run Code Online (Sandbox Code Playgroud)

另一个不太优雅的选择依赖于计算空白空间,这就是您尝试背后的想法。如果缩进有制表符,则会中断。

/^ *group foo \{/{
    match($0,/^ */) #Sets RLENGTH to the length in characters of the matched string
    i=RLENGTH
}
i                   #If i is set, the current line is printed
i&&/^ *\}$/{
    match($0,/^ */)     #Again, sets RLENGTH to the length of the matched string
    if(RLENGTH==i){i=0} #If the value is equal to the one from group foo line, unset i
}
Run Code Online (Sandbox Code Playgroud)