Matching both greedy, nongreedy and all others in

2019-07-19 17:52发布

This question already has an answer here:

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)

标签: regex pcre
3条回答
Rolldiameter
2楼-- · 2019-07-19 18:11

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.

查看更多
干净又极端
3楼-- · 2019-07-19 18:14

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
)
查看更多
欢心
4楼-- · 2019-07-19 18:17

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

查看更多
登录 后发表回答