문제

Given a string like "/foo/bar/baz/quux" (think of it like a path to a file on a unixy system), how could I (if at all possible) formulate a regular expression that gives me all possible paths that can be said to contain file quux?

In other words, upon running a regexp against the given string ("/foo/bar/baz/quux"), I would like to get as results:

  • "/foo/"
  • "/foo/bar/"
  • "/foo/bar/baz/"

I've tried the following:

  • '/\/.+\//g' - this is greedy by default, matches "/foo/bar/baz/"
  • '/\/.+?\//g' - lazy version, matches "/foo/" and also "/baz/"

P.S.: I'm using Perl-compatible Regexps in PHP in function preg_match(), for that matter)

도움이 되었습니까?

해결책

Felipe not looking for /foo/bar/baz, /bar/baz, /baz but for /foo, /foo/bar, /foo/bar/baz

One solution building on regex idea in comments but give the right strings:

  • reverse the string to be matched: xuuq/zab/rab/oof/ For instance in PHP use strrev($string )

  • match with (?=((?<=/)(?:\w+/)+))

This give you

zab/rab/oof/
rab/oof/
oof/

Then reverse the matches with strrev($string)

This give you

/foo/bar/baz
/foo/bar
/foo

If you had .NET not PCRE you could do matching right to left and proably come up with same.

다른 팁

This solution will not give exact output as you are expecting but still give you pretty useful result that you can post-process to get what you need:

$s = '/foo/bar/baz/quux';
if ( preg_match_all('~(?=((?:/[^/]+)+(?=/[^/]+$)))~', $s, $m) )
   print_r($m[0]);

Working Demo

OUTPUT:

Array
(
    [0] => /foo/bar/baz
    [1] => /bar/baz
    [2] => /baz
)

Completely different answer without reversing string.

(?<=((?:\w+(?:/|$))+(?=\w)))

This matches

foo/
foo/bar/
foo/bar/baz/

but you have to use C# which use variable lookbehind not PCRE

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top