Search code examples
regextclnon-greedy

Non-greedy match from end of string with regsub


I have a folder path like following:

/h/apps/new/app/k1999

I want to remove the /app/k1999 part with the following regular expression:

set folder "/h/apps/new/app/k1999"
regsub {\/app.+$} $folder "" new_folder

But the result is /h: too many elements are being removed.

I noticed that I should use non-greedy matching, so I change the code to:

regsub {\/app.+?$} $folder "" new_folder

but the result is still /h. What's wrong with the above code?


Solution

  • Non-greedy simply means that it will try to match the least amount of characters and increase that amount if the whole regex didn't match. The opposite - greedy - means that it will try to match as much characters as it can and reduce that amount if the whole regex didn't match.

    $ in regex means the end of the string. Therefore something.+$ and something.+?$ will be equivalent, it is just that one will do more retries before it matches.

    In your case /app.+ is matched by /apps and this is the first occurrence of /app in your string. You can fix it by being more explicit and adding the / that follows /app:

    regsub {/app/.+$} $folder "" new_folder