Q:

Can sed do backreferences in patterns defining a range?

I'm trying to use sed to pull out a brace-delimited config block like this from a long file (Junos config):
                group foo {
                    command;
                    setting {
                        value;
                    }
                    command;
                }

The trick is to stop at the } that's indented the same as the first line.
I learned how to use sed to match from one pattern to another, and tried this:
$ sed -rn '/^( *)group foo/,/^\1\}/p' config.txt
sed: -e expression #1, char 41: Invalid back reference

Is the problem that /^( *)group foo/ and /^\1\}/ are two separate patterns, and backreferences won't work between them? If so, how can I accomplish this?

A:

You are right: Although backreferences are defined in basic regular expressions (BRE) (and since each sed address is a BRE, it supports back-references), a backreference cannot retrieve the capture group defined in another BRE. So the capture group in the address /^( *)group foo/ cannot be retrieved by the other address /^\1\}/.
This test.awk does it by counting opening and closing braces:
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

$ 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;
                }

Another less elegant option which relies on counting the empty spaces, as was the idea behind your attempt. It breaks if the indenting has tabs.
/^ *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
}

