Regex - split by "_" and exclude file extension

Viewed 310

I need to split the following string AAA_BBB_CCC.extension by "_" and exclude from the results any file extension. Where A, B and C can be any character or space. I wish to get AAA, BBB and CCC.

I know that \.(?:.(?!\.))+$ will match .extension but I could not combine it with matching "_" for splitting.

3 Answers

Use the Path.GetFileNameWithoutExtension function to strip the extension from the file name.

Then use String.Split to get an array with three items:

var fileName = Path.GetFileNameWithoutExtension(fullName);
var parts = fileName.Split('_');
var partAAA = parts[0];
var partBBB = parts[1];
var partCCC = parts[2];

If the parts are always the same fixed number of characters long, you can as well extract them using the Substring function. No need to resort to regex here.

Another option is to make use of the .NET Group.Captures property and capture any char except an _ in a named capture group, which you can extract from the match using a named group.

^(?'val'[^_]+)(?:_(?'val'[^_]+))+\.\w+$

Explanation

  • ^ Start of string
  • (?'val'[^_]+) Named group val, match 1+ chars other than _ using a negated character class
  • (?: Non caputure group
    • _(?'val'[^_]+) Match an _ and capture again 1+ chars other than _ in same named group val
  • )+ Close the non capture group and repeat 1+ times for at least 1 occurrence with _
  • \.\w+ Match a . and 1+ word chars
  • $ End of string

Regex demo

string pattern = @"^(?'val'[^_]+)(?:_(?'val'[^_]+))+\.\w+$";
string input = @"AAA_BBB_CCC.extension";            
Match m = Regex.Match(input, pattern);
foreach (Capture capture in m.Groups["val"].Captures) {
   Console.WriteLine(capture.Value);
}

Output

AAA
BBB
CCC

enter image description here

If you wanted to use a regex based approach here, you could try doing a find all on the following regex pattern:

[^_]+(?=.*\.\w+$)

This pattern will match every term in between underscore, except for the portion after the extension, which will be excluded by the lookahead.

Regex rx = new Regex(@"[^_]+(?=.*\.\w+$)");
string text = "AAA_BBB_CCC.extension";
MatchCollection matches = rx.Matches(text);
foreach (Match match in matches)
{
    Console.WriteLine(match.Groups[0].Value);
}

This prints:

AAA
BBB
CCC
Related