PHP preg_grep reverse pattern matching

I built a simple code that parses all the music folders inside several disks and puts the list in an array.

Folder names begin with a few spaces when they are categories, with one space when they are "destination folders". For instance. see this structure:

[0] => /Volumes/SAMPLES/ VOCALS/ [1] => /Volumes/SAMPLES/ VOCALS/ AFRICA/ [2] => /Volumes/SAMPLES/ VOCALS/ AcmeInc Club Vocals/ [3] => /Volumes/SAMPLES/ VOCALS/ AtomicInc Dance Vocals/ [4] => /Volumes/SAMPLES/ VOCALS/ AFRICA/ AfroInc Zulu Vocals/ [5] => /Volumes/SAMPLES/ VOCALS/ AFRICA/ SampleInc Warriors/ [6] => /Volumes/SAMPLES/ VOCALS/ AFRICA/ SampleInc Warriors/SampleInc_Warriors_Ululation/ [7] => /Volumes/SAMPLES/ VOCALS/ AFRICA/ SampleInc Warriors/SampleInc_Warriors_Drums/ 

etc. I need to select only the final folders and try several combinations of greedy and non-greedy templates, starting with the final $ For example. the following path does not work:

 $pattern = "#\/ ([:alnum:]+?)/$#i"; $matches = preg_grep ($pattern, $root); 

Expected Result:

 [3] => /Volumes/SAMPLES/ VOCALS/ AcmeInc Club Vocals/ [4] => /Volumes/SAMPLES/ VOCALS/ AtomicInc Dance Vocals/ [5] => /Volumes/SAMPLES/ VOCALS/ AFRICA/ AfroInc Zulu Vocals/ [6] => /Volumes/SAMPLES/ VOCALS/ AFRICA/ SampleInc Warriors/ 

Instead, I get all the folders, or neither, nor orphans. Please note that special characters, for example, or! may be in the folder name. Thanks for the suggestions, 3 days, tried everything, desperately, thanks!

+5
source share
2 answers

Here is a valid regex:

 '~/(?: +[^/\s]+)*/ [^/\s]+(?: +[^/\s]+)*/$~' 

Watch the regex demo

It corresponds to:

  • /(?: +[^/\s]+)* - not a final subfolder ( / , then more than 1 space, 1 or more characters except space or / )
  • / - slash with a space after it
  • [^/\s]+ - 1 or more characters, except space or forward slash
  • (?: +[^/\s]+)* - 0 or more sequences ...
    • + - 1 or more regular spaces
    • [^/\s]+ - 1 or more characters, except space or forward slash
  • / - slash
  • $ - end of line

See the PHP demo :

 $ar = array("/Volumes/SAMPLES/ VOCALS/", "/Volumes/SAMPLES/ VOCALS/ AFRICA/", "/Volumes/SAMPLES/ VOCALS/ AcmeInc Club Vocals/", "/Volumes/SAMPLES/ VOCALS/ AtomicInc Dance Vocals/", "/Volumes/SAMPLES/ VOCALS/ AFRICA/ AfroInc Zulu Vocals/", "/Volumes/SAMPLES/ VOCALS/ AFRICA/ SampleInc Warriors/", "/Volumes/SAMPLES/ VOCALS/ AFRICA/ SampleInc Warriors/SampleInc_Warriors_Ululation/", "/Volumes/SAMPLES/ VOCALS/ AFRICA/ SampleInc Warriors/SampleInc_Warriors_Drums/", "/Volumes/SAMPLES/ VOCALS/ AFRICA/ AfroInc Zulu Vocals/ Folder1/" ); $n = preg_grep('~/(?: +[^/\s]+)*/ [^/\s]+(?: +[^/\s]+)*/$~', $ar); print_r($n); 

Result:

 Array ( [2] => /Volumes/SAMPLES/ VOCALS/ AcmeInc Club Vocals/ [3] => /Volumes/SAMPLES/ VOCALS/ AtomicInc Dance Vocals/ [4] => /Volumes/SAMPLES/ VOCALS/ AFRICA/ AfroInc Zulu Vocals/ [5] => /Volumes/SAMPLES/ VOCALS/ AFRICA/ SampleInc Warriors/ ) 
+3
source

You only need to make sure that the next character after the space is also not space.

 $result = preg_grep('~/ [^/ ][^/]*/\z~', $root); 

more details:

 / # literal slash [ ] # literal space [^/ ] # a character except a slash or a space [^/]* # zero or more characters that are not a slash / # literal slash \z # end of the string 

demo

+1
source

Source: https://habr.com/ru/post/1234310/


All Articles