replaceRE function not allowing functions on the replacement

I’ve got a problem where I need to take a map where the keys are snake_case and I need to convert them in to camelCase.

I’ve tried variations like below (where $key is example_field):
replaceRE "_([a-z])" ("$1" | upper) $key // 'examplefield'
replaceRE "_([a-z])" (upper "$1") $key // 'examplefield'

The replacement is verbatim $1 with no upper applied to it, as I’d expect.

If I change $1 to a regular string, the replacement does work however, e.g.:
replaceRE "_([a-z])" ("test" | upper) $key // 'exampleTESTield'
replaceRE "_([a-z])" (upper "test") $key // 'exampleTESTield'

I’m not sure how $1 behaves under-the-hood, but I don’t know how I can use it with a filter function, or how I can use replaceRE to perform more advanced replacements than just returning groups.


In your provided code block above "$1" is wrapped in quotes hence it becomes a string.
Try removing the quotes around $1.

If that does not fix your problem I suggest that you share a sample repo as the info you provide is not enough and we need to see the context.

Thanks @alexandros I did try that approach but Hugo fails the build as it’s an undefined variable, which makes sense as replaceRE doesn’t expose it as a local variable (much like PHP where group matched variables like $1, $2 etc aren’t exposed as variables, but only used in replacement).

I did read the rules on a sample repository but as this is a one-line issue with no context required beyond replaceRE I didn’t spin up a repo (and I can’t share the one I’m currently working on).

I’m really not sure how to make this work as calling upper or a function on "$1" is what will be passed to replaceRE. Only alternative I can think of is to split on underscores…

Where are you running this function? I’d change the source material, then you can use anything your shell can use.

Thanks @maiki, unfortunately I cannot change the source in this instance. Particularly because of how Hugo / Viper handles parameters in YAML config. This function runs in a partial template, I’m not sure where else to put this “logic”, as much as I’d rather avoid lots of logic in the template.

I need the keys to be camelCased, but defining the keys in YAML as camelCase is not effective as once the parameters are available to the template, they have been lowercased. So to work around this, we’ve made the keys snake_cased, and then in the template they’re converted to camelCase – this is a requirement to pass some variables to a third party JS library.

This is not pretty… but works:

{{ $foo := "abc_def_ghi" }}
{{ $regexp := "_([a-z])" }}
{{ $matches := findRE $regexp $foo }}
{{ range $matches }}
    {{ $foo = $foo | replaceRE . (upper .) }}
{{ end }}
{{ $foo = $foo | replaceRE "_" "" }}
{{ printf "%s" $foo }} <!-- abcDefGhi -->

It’s not heavily tested, but you should be able to build up the regexp you need based on this.

1 Like

… and here’s another version which is simpler in one aspect, but over-engineered in another :nerd_face:

 .underscore {
     display: none;
 .upper {
     text-transform: uppercase;
{{ $foo := "abc_def_ghi" }}
{{ $regexp := "(_)([a-z])" }}
{{ printf "%s" $foo | replaceRE $regexp "<span class=underscore>${1}</span><span class=upper>${2}</span>" | safeHTML }}
1 Like

replaceRE uses regexp.ReplaceAllString in the background, so it won’t allow what you’re wanting (as you’ve seen). I doubt we want to add a framework for allowing regexp.ReplaceAllStringFunc from the templates, which could allow what you’re trying to do.

For your use case, it might be simpler to add funcs from a package like, namely Camelize.

1 Like

Having this feature will add a lot of power (over the one we already have :slight_smile:) to the templates. Is it too complicated to enable what the OP wants to do? Would it be possible to make replaceRE's returned regex subgroups to be operable by other template funcs?