4

For the following code:

local function getParentPath(_path)

    pattern = "(.+)([/\\][/\\])(.+)"
    i,j,k = string.match(path,pattern)
    return i,j,k

end

print(getParentPath(path))

For path = "C://data//file.text", I get:

C://data // file.text

But For path = "C:\data\file.text", I get:

nil nil nil

I am looking for a pattern which woks for both. Any suggestions?

tanzil
  • 1,461
  • 2
  • 12
  • 17
  • Can you elaborate in more details what did you expect to match? Everything up to last `//`? There's two of them in your string and it is not clear what you really want just from one example. – Oleg V. Volkov Mar 24 '16 at 16:22
  • sorry I re framed my question – tanzil Mar 24 '16 at 16:30

2 Answers2

5

The problem is that the first .+ matches greedily and grabs all up to the last \ and then backtracks. Then, one \ can be matched with [\\/], and thus the first group has one backslash, and the second has got the second.

You can fix it by using

pattern = "^(.-)([/\\]+)([^/\\]+)$"

See IDEONE demo

Explanation:

  • ^ - start of string
  • (.-) - any characters but as few as possible (lazy matching with - quantifier)
  • ([/\\]+) - 1+ / or \
  • ([^/\\]+) - 1+ characters other than / and \
  • $ - end of string
Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563
3

It is perfectly expected. First greedy (.+) matches as many symbols as it can without breaking following patterns - i.e. everything up to very last slash that is necessary to make ([/\\]+) match.

Oleg V. Volkov
  • 21,719
  • 4
  • 44
  • 68