I am currently trying to create a random image generator in PHP, and I'm having a hard time setting the file path, I can get all the file paths, but they are in one long string, like this.
" ../images/box1/IMG_3158.JPG../images/box1/IMG_3161.JPG../images/box1/IMG_3163.JPG../images/box1/IMG_3158.JPG../images/box1/IMG_3161.JPG../images/box1/IMG_3163.JPG"
with the " .." marking the beginning of a new file.
How would i explode ( or something of the kind ) each file_path to return them separately?
Here is one way you can do this.
$data = '../images/box1/IMG_3158.JPG../images/box1/IMG_3161.JPG../images/box1/IMG_3163.JPG../images/box1/IMG_3158.JPG../images/box1/IMG_3161.JPG../images/box1/IMG_3163.JPG';
$files = preg_split('/(?<!^)(?=\.{2})/', $data);
print_r($files);
Output
Array
(
[0] => ../images/box1/IMG_3158.JPG
[1] => ../images/box1/IMG_3161.JPG
[2] => ../images/box1/IMG_3163.JPG
[3] => ../images/box1/IMG_3158.JPG
[4] => ../images/box1/IMG_3161.JPG
[5] => ../images/box1/IMG_3163.JPG
)
Regular Expression:
(?<! look behind to see if there is not:
^ the beginning of the string
) end of look-behind
(?= look ahead to see if there is:
\.{2} '.' (2 times)
) end of look-ahead
<?php
//Since new file path is starting from ".." we explode it using ".." and added to each file path.
$string ="../images/box1/IMG_3158.JPG../images/box1/IMG_3161.JPG../images/box1/IMG_3163.JPG../images/box1/IMG_3158.JPG../images/box1/IMG_3161.JPG../images/box1/IMG_3163.JPG";
$file_path=explode('..',$string);
$i=0;
while(isset($file_path[++$i])){
$file_path[$i]="..".$file_path[$i];
echo $file_path[$i]."<br />";
}
?>
http://ideone.com/MTRr9Q
Just use explode()
$file_paths = explode('..', $input);
Example
$string = "../images/box1/IMG_3158.JPG../images/box1/IMG_3161.JPG../images/box1/IMG_3163.JPG../images/box1/IMG_3158.JPG../images/box1/IMG_3161.JPG../images/box1/IMG_3163.JPG";
$file_paths = explode('..', $string);
var_dump($file_paths);
This strips of the ".." at the beginning, so try to append it yourself. For more complicated situations, a preg_split() would be an appropriate task. Given that your string doesn't change, then an explode could do.
If you are able to introduce an otherwise unused character between each path as you import(?) the list of path names, you could then use that character as your delimiter instead of ".." (refer to Ali's answer).
Related
I am fairly new to regex. I have been trying to break string to get the initial part of the string to create folders.
Here are few examples of the variables that I need to break.
test1-792X612.jpg
test-with-multiple-hyphens-612X792.jpg
Is there a way using regular expression that I can get test1 and test-with-multiple-hyphens?
You can use a regex like this:
(.*?)-\d+x\d+
Working demo
The idea is that the pattern will match the string with the -NumXNum but capture the previous content. Note the case insensitive flag.
MATCH 1
1. [0-5] `test1`
MATCH 2
1. [18-44] `test-with-multiple-hyphens`
If you don't want to use the insensitive flag, you could change the regex to:
(.*?)-\d+[Xx]\d+
If you're certain that all filenames end with 000X000 (where the 0's are any number), this should work:
/^(.*)-[0-9]{3}X[0-9]{3}\.jpg$/
The value from (.*) will contain the part that you're looking for.
In case there could be more or fewer numbers, but at least one:
/^(.*)-[0-9]+X[0-9]+$\.jpg/
You can use this simple regex:
(.+)(?=-.+$)
Explanations:
(.+) : Capture desired part
(?=-.+$) : (Positive Lookahead) Which is following a dashed part
Live demo
If I understood your question correctly, you want to break the hyphenated parts of a file into directories. The expression (.*?)-([^-]+\.jpg)$ will capture everything before and after the last - in a .jpg file. You can then use preg_match() to match/capture these groups and explode() to split the - into different directories.
$files = array(
'test1-792X612.jpg',
'test-with-multiple-hyphens-612X792.jpg',
);
foreach($files as $file) {
if(preg_match('/(.*?)-([^-]+\.jpg)$/', $file, $matches)) {
$directories = explode('-', $matches[1]);
$file = $matches[2];
}
}
// 792X612.jpg
// Array
// (
// [0] => test1
// )
//
// 612X792.jpg
// Array
// (
// [0] => test
// [1] => with
// [2] => multiple
// [3] => hyphens
// )
I have bunch of strings like this:
a#aax1aay222b#bbx4bby555bbz6c#mmm1d#ara1e#abc
And what I need to do is to split them up based on the hashtag position to something like this:
Array
(
[0] => A
[1] => AAX1AAY222
[2] => B
[3] => BBX4BBY555BBZ6
[4] => C
[5] => MMM1
[6] => D
[7] => ARA1
[8] => E
[9] => ABC
)
So, as you see the character right behind the hashtag is captured plus everything after the hashtag just right before the next char+hashtag.
I've the following RegEx which works fine only when I have a numeric value in the end of each part.
Here is the RegEx set up:
preg_split('/([A-Z])+#/', $text, 0, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
And it works fine with something like this:
C#mmm1D#ara1
But, if I change it to this (removing the numbers):
C#mmmD#ara
Then it will be the result, which is not good:
Array
(
[0] => C
[1] => D
)
I've looked at this question and this one also, which are similar but none of them worked for me.
So, my question is why does it work only if it has followed by a number? and how I can solve it?
Here you can see some of them sample strings which I have:
a#123b#abcc#def456 // A:123, B:ABC, C:DEF456
a#abc1def2efg3b#abcdefc#8 // A:ABC1DEF2EFG3, B:ABCDEF, C:8
a#abcdef123b#5c#xyz789 // A:ABCDEF123, B:5, C:XYZ789
P.S. Strings are case-insensitive.
P.P.S. If you ever thinking what the hell are these strings, they are user submitted answers to a questionnaire, and I can't do anything on them like refactoring as they are already stored and just need to be proceed.
Why Not Using explode?
If you look at my examples you will see that I need to capture the character right before the # as well. If you think it's possible with explode() please post the output as well, thanks!
Update
Should we focus on why /([A-Z])+#/ works only if numbers included? thanks.
Instead of using preg_split(), decide what you want to match instead:
A set of "words" if followed by either <any-char># or <end-of-string>.
A character if immediately followed by #.
$str = 'a#aax1aay222b#bbx4bby555bbz6c#mmm1d#ara1e#abc';
preg_match_all('/\w+(?=.#|$)|\w(?=#)/', $str, $matches);
Demo
This expression uses two look-ahead assertions. The results are in $matches[0].
Update
Another way of looking at it would be this:
preg_match_all('/(\w)#(\w+)(?=\w#|$)/', $str, $matches);
print_r(array_combine($matches[1], $matches[2]));
Each entry starts with a single character, followed by a hash, followed by X characters until either the end of the string is encountered or the start of a next entry.
The output is this:
Array
(
[a] => aax1aay222
[b] => bbx4bby555bbz6
[c] => mmm1
[d] => ara1
[e] => abc
)
If you still want to use preg_split you can remove the + and it might work as expected:
'/([A-Z])#/i'
Since then you only match the hashtag and ONE alpha character before, and not all them.
Example: http://codepad.viper-7.com/z1kFDb
Edit: Added a case-insensitive flag i in the pattern.
Use explode() rather than Regexp
$tmpArray = explode("#","a#aax1aay222b#bbx4bby555bbz6c#mmm1d#ara1e#abc");
$myArray = array();
for($i = 0; $i < count($tmpArray) - 1; $i++) {
if (substr($tmpArray[$i],0,-1)) $myArray[] = substr($tmpArray[$i],0,-1);
if (substr($tmpArray[$i],-1)) $myArray[] = substr($tmpArray[$i],-1);
}
if (count($tmpArray) && $tmpArray[count($tmpArray) - 1]) $myArray[] = $tmpArray[count($tmpArray) - 1];
edit: I updated my answer to reflect better reading the questions
You can use explode() function that will split the string except the hash signs, like stated in the answers given before.
$myArray = explode("#",$string);
For the string 'a#aax1aay222b#bbx4bby555bbz6c#mmm1d#ara1e#abc' this returns something like
$myarray = array('a', 'aax1aay22b', 'bbx4bby555bbz6c' ....);
All you need now is to take the last character of each string in array as another item.
$copy = array();
foreach($myArray as $item){
$beginning = substr($item,0,strlen($item)-1); // this takes all characters except the last one
$ending = substr($item,-1); // this takes the last one
$copy[] = $beginning;
$copy[] = $ending;
} // end foreach
This is an example, not tested.
EDIT
Instead of substr($item,0,strlen($item)-1); you might use substr($item,0,-1);.
I'm trying to make a main menu bar link dynamic, based on the visitor's current page.
I started with
$path = $_SERVER['REQUEST_URI'];
Which, of course, returns things like
/subfolder/page.html
/subfolder1/subfolder2/page.html
/page.html
I need to grab whatever is after the first '/'. I've tried messing around with explode, but I stumble with what to do with the resulting array. I'm also going cross-eyed trying to write a regex - seems a more elegant solution.
Then I need to build my switch. Something along the lines of:
switch ($path)
{
case '/subfolder0':
$link = $root_url.'/subfolder0/anotherfolder/page.html';
break;
case '/subfolder1':
$link = $root_url.'/subfolder1/page.html';
break;
default:
$link = $root_url.'/subfolder2/page.html';
}
Finally, should I be using if...elseif for this in lieu of switch?
Thanks for your time, all!
To grab everything after the first /:
strstr($_SERVER['REQUEST_URI'], '/');
Or, with regex:
preg_match('#(/.*)#', $_SERVER['REQUEST_URI'], $matches); // $matches[1] will be the path
As far as the switch, I'd say if/elseif/else is the least-elegant in your case, switch isn't bad, but personally I'd go with an associative array:
$mapping = array('/subfolder0' => $root_url.'/subfolder0/anotherfolder/page.html', 'etc' => 'etc');
$link = $mapping($path);
This lets you keep the mapping in another file for organization, and makes it a little bit easier to maintain by separating configuration from implementation.
Using explode is not at all a bad idea if you are interested in all the parts of the URI, you should take a look at the documentation for explode
Its usage would be like so:
$exploded = explode('/','/path/to/page.html');
echo $exploded[0]; // Will print out '' (empty string)
echo $exploded[1]; // Will print out 'path'
echo $exploded[2]; // Will print out 'to'
echo $exploded[3]; // Will print out 'page.html'
However as far as I understand, you are looking to replace the link by whatever is after the first character (which is always '/'), you could use substr like so:
// Get whatever is after the first character and put it into $path
$path = substr($_SERVER['REQUEST_URI'], 1);
In your case, it is not needed because you are able to predict there is a backslash at the beginning of the string.
I would also suggest using an associative array to replace the URL.
I would implement the entire thing like so (removing the first backslash as you require):
// Define the URLs for replacement
$urls = array(
'subfolder0' => '/subfolder0/anotherfolder/page.html',
'subfolder1' => '/subfolder1/page.html'
);
// Get the request URI, trimming its first character (always '/')
$path = substr($_SERVER['REQUEST_URI'], 1);
// Set the link according to $urls associative array, or set
// the default URL if not found
$link = $urls[$path] or '/subfolder2/page.html';
Or with explode, taking only the first part of the URI:
// Get the parts of the request
$requestParts = explode('/', $_SERVER['REQUEST_URI']);
// Set the link according to $urls associative array, or set
// the default URL if not found
$link = $urls[$requestParts[1]] or '/subfolder2/page.html';
After analyzing the OP's question, I think he/she meant to phrase it as "Everything after the first '/', but before the second '/'. Here is what I got:
You could try this regex:
<?php
/*
* Regex: /((\w+?|\w+\.\w+?)(?!^\/))(?=\/.*$|$)/
*/
$paths = array(
'/subfolder9/',
'/subfolder/page.html',
'/subfolder1/subfolder2/page.html',
'/page.html'
);
foreach ($paths as $path) {
preg_match("/((\w+?|\w+\.\w+?)(?!^\/))(?=\/.*$|$)/", $path, $matches);
debug($matches);
}
// $matches[1] will contain the first group ( ) matched in the expression.
// or "subfolder<#>" or "<page>.<ext>"
// The loop results is as follows:
Array
(
[0] => subfolder9
[1] => subfolder9
[2] => subfolder9
)
Array
(
[0] => subfolder
[1] => subfolder
[2] => subfolder
)
Array
(
[0] => subfolder1
[1] => subfolder1
[2] => subfolder1
)
Array
(
[0] => page.html
[1] => page.html
[2] => page.html
)
?>
Note: This only works with regex flavors that support look-arounds (zero-width positive & negative look ahead are the ones used the example.)
This a great cheat sheet for regular expressions and I don't code without it.
Regular-Expressions.info - (click to view)
You can just use dirname function to get what you want:
$path = dirname('/subfolder/page.html'); // returns '/subfolder'
$path = dirname('/subfolder1/subfolder2/page.html'); // returns '/subfolder1'
$path = dirname('page.html'); // returns '.'
EDIT: Regex based solution:
$path = preg_replace('#^(/[^/]*).*$#', '$1', '/subfolder/page.html' )
I'd like to remove all parentheses from a set of strings running through a loop. The best way that I've seen this done is with the use of preg_replace(). However, I am having a hard time understanding the pattern parameter.
The following is the loop
$coords= explode (')(', $this->input->post('hide'));
foreach ($coords as $row)
{
$row = trim(preg_replace('/\*\([^)]*\)/', '', $row));
$row = explode(',',$row);
$lat = $row[0];
$lng = $row[1];
}
And this is the value of 'hide'.
(1.4956873362063747, 103.875732421875)(1.4862491569669245, 103.85856628417969)(1.4773257504016037, 103.87968063354492)
That pattern is wrong as far as i know. i got it from another thread, i tried to read about patterns but couldn't get it. I am rather short on time so I posted this here while also searching for other ways in other parts of the net. Can someone please supply me with the correct pattern for what I am trying to do? Or is there an easier way of doing this?
EDIT: Ah, just got how preg_replace() works. Apparently I misunderstood how it worked, thanks for the info.
I see you actually want to extract all the coordinates
If so, better use preg_match_all:
$ php -r '
preg_match_all("~\(([\d\.]+), ?([\d\.]+)\)~", "(654,654)(654.321, 654.12)", $matches, PREG_SET_ORDER);
print_r($matches);
'
Array
(
[0] => Array
(
[0] => (654,654)
[1] => 654
[2] => 654
)
[1] => Array
(
[0] => (654.321, 654.12)
[1] => 654.321
[2] => 654.12
)
)
I don't understand entirely why you would need preg_replace. explode() removes the delimiters, so all you have to do is remove the opening and closing parantheses on the first and last string respectively. You can use substr() for that.
Get first and last elements of array:
$first = reset($array);
$last = end($array);
Hope that helps.
"And this is the value of $coords."
If $coords is a string, your foreach makes no sense. If that string is your input, then:
$coords= explode (')(', $this->input->post('hide'));
This line removes the inner parentheses from your string, so your $coords array will be:
(1.4956873362063747, 103.875732421875
1.4862491569669245, 103.85856628417969
1.4773257504016037, 103.87968063354492)
The pattern parameter accepts a regular expression. The function returns a new string where all parts of the original that match the regex are replaced by the second argument, i.e. replacement
How about just using preg_replace on the original string?
preg_replace('#[()]#',"",$this->input->post('hide'))
To dissect your current regex, you are matching:
an asterisk character,
followed by an opening parenthesis,
followed by zero or more instances of
any character but a closing parenthesis
followed by a closing parenthesis
Of course, this will never match, since exploding the string removed the closing and opening parentheses from the chunks.
Let's say I might have a couple of directories stored in a string.. they might look like this
/something/WHATEVER/websites/dev/tools/tests/media/upload.ini
/something/WHATEVER/websites/dev/tools/tests/get/add.ini
etc.
How can I extract the names "media" and "get" from those two links up there? I would probably have to use regular expressions but how would it look like?
Use php function explode? http://php.net/manual/en/function.explode.php
$str="one ,two , three , four ";
print_r(array_map('trim',explode(",",$str)));
Output:
Array ( [0] => one [1] => two [2] => three [3] => four )
If you want to use regexes, it might look like this
/([^/]+)/[^/]+$
i.e.,
preg_match('`/([^/]+)/[^/]+$`',$fullpath,$matches)
$matches[1] will contain your directory.
I would normally suggest sscanf for such easy patterns:
$string = '/something/WHATEVER/websites/dev/tools/tests/media/upload.ini';
$format = '/something/WHATEVER/websites/dev/tools/tests/%[^/]';
$r = sscanf($string, $format, $name);
Next to that there are standard PHP dirname functions that are helpful in case you need this more dynamic, e.g. the last directory name of a filename:
$string = '/something/WHATEVER/websites/dev/tools/tests/media/upload.ini';
$reduce = explode('/', dirname($string));
$name = end($reduce);
Demo