john c. j.
john c. j.

Reputation: 1175

A regex to split a file path

I want to create a regex to split a path as shown in the following scheme:

Path:        c:\foo\bar\baz.txt
Root name:   c:
Parent path: c:\foo\bar
Filename:    baz.txt
Stem:        baz
Extension:   txt

Here is what I have. The problem is that it doesn't work when I have a filename without an extension:

^(([aA-zZ]:)\\(?:[^:]+))\\(([^\\]+)\.([^\.]+))$

I can change it to

^(([aA-zZ]:)\\(?:[^:]+))\\(([^\\]+)(\.([^\.]+))?)$

but it doesn't split a filename to a stem and an extension.

Upvotes: 3

Views: 4685

Answers (2)

anubhava
anubhava

Reputation: 785186

You may use this regex with a lazy quantifier and an optional group:

^(([a-zA-Z]:)(?:\\[^:]+)?)\\(([^\\\n]+?)(?:\.([^.\n]+))?)$

RegEx Demo

It is important to make ([^\\]+?) a lazy match to avoid it matching too much when next non-capture group i.e. (?:\.([^.\n]+))? is an optional match.

Upvotes: 3

thibsc
thibsc

Reputation: 4049

A possible solution to split your path is to use regex group (Demo here):

Regex explanation with 'c:\foo\bar\baz.txt':

  • The first thing is the drive: (?<drive>[a-z]:) -> 'c:'
  • The last thing is the file: (?<file>(?<fname>\\w+)(?:\.(?<fext>\w+))?)
    • (?<fname>\\w+) -> 'baz'
    • (?<fext>\\w+) -> 'txt'
  • Then the parent path is drive + a repetion of \\\w+\\?: (?<ppath>(?<drive>[a-z]:)(?:\\\w+\\?)+)

So the full path is drive + parent path + file:
(?<fullpath>(?<ppath>(?<drive>[a-z]:)(?:\\\w+\\?)+)(?<file>(?<fname>\w+)(?:\.(?<fext>\w+))?)$)

// Example without group
const path = 'c:\\foo\\bar\\baz.txt';
const regex = /([a-z]:)((?:\\?\w+\\)+)((\w+)(?:\.(\w+))?)/;
const found = path.match(regex);

// console.log(found); // Array ["c:\foo\bar\baz.txt", "c:", "\foo\bar\", "baz.txt", "baz", "txt"]
console.log('Root name:\t' + found[1]); // drive
console.log('Parent path:\t' + found[1]+found[2]); // Parent path
console.log('Filename:\t' + found[3]); // File name
console.log('Stem:\t\t' + found[4]); // Stem
console.log('Extension:\t' + found[5]); // Extension

// Java example with group
String s = "c:\\foo\\bar\\baz.txt";
Pattern p = Pattern.compile("(?<fullpath>(?<ppath>(?<drive>[a-z]:)(?:\\\\\\w+\\\\?)+)(?<file>(?<fname>\\w+)(?:\\.(?<fext>\\w+))?)$)");
Matcher m = p.matcher(s);

while (m.find()) {
    System.out.println("Path:\t\t" + m.group("fullpath"));
    System.out.println("Root name:\t" + m.group("drive"));
    System.out.println("Parent path:\t" + m.group("ppath"));
    System.out.println("Filename:\t" + m.group("file"));
    System.out.println("Stem:\t\t" + m.group("fname"));
    System.out.println("Extension:\t" + m.group("fext"));
}
/* OUTPUT */
Path:           c:\foo\bar\baz.txt
Root name:      c:
Parent path:    c:\foo\bar\
Filename:       baz.txt
Stem:           baz
Extension:      txt

Upvotes: 3

Related Questions