-1

Given the following strings:

'/a/xxx/b/c/xxx/xxx/d/e/xxx/xxx/f/g'
'/a/xxx/b/c/xxx/xxx/d/e/xxx/xxx/f/'
'/a/xxx/b/c/xxx/xxx/d/e/xxx/xxx/f'
'/a/xxx/b/c/xxx/xxx/d/e/xxx/xxx/f/g/xxx/xxx'

I'm looking for a regex that will match

/a/xxx/b/c/xxx/xxx/d/e/xxx/xxx/f

for all of the above strings

That is, match everything until the last occurrence of this pattern:

{forward slash or start of string} then {xxx} then {forward slash} then {any group of chars (except forward slash) that is not equal to xxx } then {forward slash or end of string}

I do not know how to translate the above pattern into a regex.

The .*\/ pattern I tried does not solve the problem.

Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563
Kawd
  • 4,122
  • 10
  • 37
  • 68
  • @WiktorStribiżew Thanks for your always good regexs. I think this isn't a dupplicate of what you linked, because that answers include the /. – Jorge.V Jul 06 '18 at 09:09
  • @WiktorStribiżew nevermind, OP edited question and fully changed it. – Jorge.V Jul 06 '18 at 09:10
  • @SproutCoder What is the code/pattern that does not work for you? Your current title and *match everything until the last occurrence of this pattern* requirement is in line with [this post](https://stackoverflow.com/questions/24465512/regular-expression-to-match-everything-until-the-last-occurrence-of). Please update the question if that solution does not work for you. – Wiktor Stribiżew Jul 06 '18 at 09:11
  • @SproutCoder I don't understand your edit. Why does /a/xxx/b/c/xxx/xxx/d/e/xxx/xxx/f match entirely and not /a/xxx/b/c/xxx/xxx/d/e/xxx/xxx since the last /whatever shouldn't be included? And where is the g for the last supposed good match? Shouldn't it just remove the /xxx.. part? In fact shouldn't it remove only the last /xxx? – Jorge.V Jul 06 '18 at 09:14
  • 1
    So, https://regex101.com/r/UYvZDh/6 works as expected,right? – Wiktor Stribiżew Jul 06 '18 at 11:36
  • yes it looks like this is the correct answer, I can't think of any other edge cases, it looks like this is following the exact pattern I mentioned – Kawd Jul 06 '18 at 11:39
  • Ok, note that `{anything but xxx}` is not clear in the question, it can be understood as `(?:(?!xxx).)*` to match any char, 0+ times, that does not start `xxx` sequence. And what you need is `{any subpart not equal to xxx}`. – Wiktor Stribiżew Jul 06 '18 at 11:41

1 Answers1

1

You may use

/(?:.*\/)?xxx\/(?!xxx(?![^\/]))[^/]*(?=$|\/)/

See the regex demo.

Details

  • (?:.*\/)? - an optional group matching
    • .* - any 0+ chars other than line break chars, as many as possible
    • \/ - a / char
  • xxx\/ - a xxx/ substring
  • (?!xxx(?![^\/])) - the text starting at the next location in string cannot be equal to xxx/ or xxx at the end of the string
  • [^/]* - any 0+ chars other than / as many as possible ([^/]*)
  • (?=$|\/) - there must be end of string or / immediately to the right of the current position.

JS demo:

var strs = ['/a/xxx/b/c/xxx/xxx/d/e/xxx/xxx/f/g','/a/xxx/b/c/xxx/xxx/d/e/xxx/xxx/f/','/a/xxx/b/c/xxx/xxx/d/e/xxx/xxx/f','/a/xxx/b/c/xxx/xxx/d/e/xxx/xxx/f/g/xxx/xxx','/xxx/f/g','xxx/f/g','a/xxx/f/g','/a/xxx/f/g','/a/xxx/b/c/xxx/xxx/d/e/xxx/gggxxxd/f/gxxxf/'];
var rx = /(?:.*\/)?xxx\/(?!xxx(?![^\/]))[^/]*(?=$|\/)/;
for (var s of strs) {
  console.log(s, "=>", s.match(rx)[0]);
}
Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563