19

PLEASE READ CAREFULLY: This is a bit unusual and you will be tempted to say things like "that isn't how to use a regex" or "dude, just use String.SubString()," Etc...

I have a need to write a regex (to use a pre-existing method) that will match text BETWEEN curly braces, BUT NOT the curly braces themselves.

For Example: "{MatchThisText}" AND "La la la {MatchThisText} la la la..."
Should Both Match: "MatchThisText"

Someone asked this exact question a year ago, and he got a bunch of solutions for regexes that WILL match the curly braces in addition to "MatchThisText," resulting in a match of "{MatchThisText}" which is not what he (or I) needed.

If someone can write a Regex that actually matches only the characters BETWEEN the curly braces, I'd really appreciate it. It should allow any ASCII values, and should stop the match at the FIRST closing bracket.

For Example: "{retailCategoryUrl}/{filters}"
Should Match: retailCategoryUrl and filters
But NOT Match: "retailCategoryUrl}/{filters" (Everything but the outer braces)

Hey, this is a really tricky one for me, so please forgive the question if this is trivial for some of you.

THANKS!

Community
  • 1
  • 1
bopapa_1979
  • 8,476
  • 9
  • 44
  • 73
  • Quite easy (requires grouping, but honestly, this is a pretty fundamental feature), unless you want to consider nested braces "correctly" (e.g. as full-blown parsers do), in which case it's simply impossible (except when using those non-regex-y extensions some implementations, e.g. NET, have). –  Oct 26 '10 at 18:21
  • We'll need more context, since the solution would probably involve look-behind and look-ahead operators, so depend on the dialect of regex you are using. – Douglas Leeder Oct 26 '10 at 18:24
  • `{(\w+)}` - the brackets denote a group, which you can get the contents of. – OMG Ponies Oct 26 '10 at 18:25
  • Literally, the post that you linked to has the answer in! Simply use {([^}]*)} Which will match the whole phrase, but group 1 inside that match is what you're after. – John Wordsworth Oct 26 '10 at 18:27
  • 2
    Hey everybody. I thank you kindly for the responses. I am new to Regex. As soon as I read the word "grouping" in delnan's comment, I had the AHA! moment I was needing. I used the following Regex: {(?.*?)} The I can hit the inner group in C#: Regex regex = new Regex("{(?.*?)}"); var matches = regex.Matches("{MatchThisText}"); foreach (Match match in matches) { var key = match.Groups[1].Value; // Do something with the match } – bopapa_1979 Oct 28 '10 at 16:41

5 Answers5

17

Python:

(?<={)[^}]*(?=})

In context:

#!/usr/bin/env python

import re

def f(regexStr,target):
    mo = re.search(regexStr,target)
    if not mo:
        print "NO MATCH"
    else:
        print "MATCH:",mo.group()

f(r"(?<={)[^}]*(?=})","{MatchThisText}")
f(r"(?<={)[^}]*(?=})","La la la {MatchThisText} la la la...")

prints:

MATCH: MatchThisText
MATCH: MatchThisText
Douglas Leeder
  • 49,001
  • 8
  • 86
  • 133
  • 1
    notice that sometimes you will need to escape `{` by using something like: `(?<=\{)[^\}]*(?=\})` because some applications will trying to think about curly brackets as standing for repetition operator. – andilabs Mar 05 '15 at 12:45
12

If you're using a RegExp engine with lookahead and lookbehind support like Python, then you can use

/(?<={)[^}]*(?=})/

If it doesn't (like javascript), you can use /{([^}]*)}/ and get the substring match. Javascript example:

"{foo}".match(/{([^}]*)}/)[1] // => 'foo'

Daniel Mendel
  • 8,901
  • 1
  • 21
  • 37
8

You'll need a non-greedy match operator, *?, to stop the match as soon as the engine sees a closing curling brace. Then you need to group what's inside the braces, using parentheses. This should do it:

{(.*?)}

You will then need to get the value from group number 1 in your regex API. (How you do that depends on your programming language/API.)

steinar
  • 8,902
  • 1
  • 20
  • 36
0

current answer works with .NET Regex but need to remove the curly braces from all matches:

var regex = new Regex(@"(?<={)[^}]*(?=})", RegexOptions.Compiled);
var results = regex.Matches(source)
                   .Cast<Match>()
                   .Select(m => m.Value.TrimStart('{').TrimEnd('}'));
Community
  • 1
  • 1
Tiberiu Craciun
  • 3,071
  • 1
  • 10
  • 12
0

In Javascript you get an array with all matches. Here is an example that machtes text between css` and ` for machting template strings:

yourstring.match(/css`([^}]+).`/gmi)
pungggi
  • 1,182
  • 13
  • 25