'Replace character inside double curly brackets regex

I'm trying to replace - character with _ inside a double curly brackets.

Example inputs: Hello {{first-name}}, how are you? The event {{event-name-address}}

Example outputs: Hello {{first_name}}, how are you? The event {{event_name_address}}

This is the regex I tried to do: {{.+(-).+}}, and this is the preg_replace PHP function I tried to use: $template = preg_replace("{{.+(-).+}}", "$1_", $template);

This doesn't seems to work.

What am I doing wrong? Thanks!



Solution 1:[1]

Curve brackets should be escaped, they are regex metasymbols. Than, use two groups for parts before and after the -:

(\{\{[^}]+)-([^}]+\}\})

and replace on ${1}_$2.

[^}] is used to say "any symbol, but not }".

UPD: thank to @CarySwoveland for help with clarifying.

Solution 2:[2]

If double-braces are matched and not nested you can substitute matches of

(?<=[^{])\-(?=[^{}]+}})

with '_'. This assumes the hyphen between matched pairs of double-braces must be preceded by a character other than '{' and must be followed by a character other than '}'.1

Note this permits matching multiple hyphens with the the same matched pair of double-braces.

This relies on the assumption that if a hyphen is followed, after intervening characters that are neither open nor closed braces, by a pair of closing double-braces, that hyphen must be preceded by a pair of open double-braces, with intervening characters that are neither open nor closed braces.

Demo

The regular expression can be broken down as follow:

(?<=      # begin a positive lookbehind
  [^{]    # match a character other than '{'  
)         # end positive lookbehind
\-        # match '-'
(?=       # begin a positive lookahead
  [^{}]+  # match one or more characters other than '{' and '}'
  }}      # match '}}'
)         # end positive lookahead

1. If this is not a requirement the expression can be simplified to \-(?=[^{}]*}}).

Solution 3:[3]

You can use

preg_replace('~(?:\G(?!^)|{{)[^{}-]*\K-(?=[^{}]*}})~', '_', $template)

See the regex demo. Details:

  • (?:\G(?!^)|{{) - either the end of the previous match or {{
  • [^{}-]* - zero or more chars other than {, } and a - char
  • \K - match reset operator that omits the text matched so far from the memory buffer
  • - - a hyphen
  • (?=[^{}]*}}) - a location immediately followed by zero or more chars other than { and } and then }}.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2
Solution 3 Wiktor Stribiżew