It's more a job for perl whose regexp can more easily find matching pairs. Anyway, the few sed implementations that have a -i option for in-place editing have copied it from perl and in ways incompatible between each other.
If we assume that {/} are always matched even inside "..." strings, that could be
perl -0777 -i -pe '
s{
^ \h* filter \s* \{
( (?: [^{}]++ | \{ (?1) \} ) * )
\}
}{
$& =~ s{ ^ \h* \K \# \h* (year_n \h* =) }{$1}gmrx
}gmxe' -- your-file
Where:
-penables thesedmode where files are processed one record at a time where the equivalent ofsed's pattern space is the$_variable (on whichs{pattern}{replacement}flagsoperates by default), likesed'ss.-ifor in-place editing (copied by somesedimplementations).-0777changes the record separator from the default of newline (like insed) to some impossible byte value, so the files are processed as a whole. Same as-gin newer versions ofperl.- then we have a
s{pattern}{replacement}gmxewhere:xallows adding whitespace (and comments) in the pattern to improve legibility.mmakes it so that^matches at the start of every line in the subject instead of just as the start of the subject.eis for thereplacementto be interpreted asperlcode.\sis for any whitespace (well ASCII only by default) including newline, similar to[[:space:]]in POSIX regexp, and\hfor horizontal whitespace (ISO8859-1 ones by default, that is space, tab, and non-breaking-space encoded as 0xA0, but importantly not newline; similar to POSIX'[[:blank:]]).- The important part in there is
(?1)which recalls the regexp in the first(...)capture group so allows for recursive regexps. - The
replacementapplies anothers{pattern}{replacement}gmrxto$&which is what was matched by the first regexp with:rreturns the result of the substitution instead of applying it in place to$&\Kmarks the start of what's toKeep from the match, so we don't discard what's matched to the left of it.