Search nested namedtuples by key

First of all, it might be that NamedTuple is not the right type for your application.
If you want to do a lot of alternation of your data at runtime, then a Dict might be better suited, since NamedTuples lead to a bit of compilation each time.

However, the function propertynames gives you access to the keys and values gives you the values. With these, you can probably do whatever you want with pure Julia. Following your example,
let’s say you want to recursively replace all occurrences of gr with g, then you could do

function replace_gr(nt::NamedTuple)
    new_keys   = replace(propertynames(nt), :gr => :g )
    new_values = replace_gr.(values(nt))
    return NamedTuple{new_keys}(new_values)
end
replace_gr(nt) = nt  # use multiple dispatch to ignore all non NamedTypes

replace_gr(nt)  # -> (g = 'a', f1 = 1, f2 = (g = 'b', f21 = 21))

By the way, if you just want to replace a value, you could do nt_replace_f1 = (; nt..., f1 = 10).