I have a PHP string with a list of items, and I would like to get the last one.
The reality is much more complex, but it boils down to:
$Line = 'First|Second|Third';
if ( preg_match( '#^.*|(?P<last>.+)$#', $Line, $Matches ) > 0 )
{
print_r($Matches);
}
I expect Matches['last'] to contain 'Third', but it does not work. Rather, I get Matches[0] to contain the full string and nothing else.
What am I doing wrong?
Please no workarounds, I can do it myself but I would really like to have this working with preg_match
You have this:
'#^.*|(?P<last>.+)$#'
^
... but I guess you are looking for a literal |:
'#^.*\|(?P<last>.+)$#'
^^
Just use :
$Line = 'First|Second|Third' ;
$lastword = explode('|', $line);
echo $lastword['2'];
If your syntax is always kinda the same, and by that I mean that uses the | as separator, you could do the following, if you like it.
$Line = 'First|Second|Third' ;
$line_array = explode('|', $Line);
$line_count = count($line_array) - 1;
echo $line_array[$line_count];
or
$Line = 'First|Second|Third' ;
$line_array = explode('|', $Line);
end($line_array);
echo $line_array[key($line_array)];
Example of PHP preg_match to get the last match:
<?php
$mystring = "stuff://sometext/2010-01-01/foobar/2016-12-12.csv";
preg_match_all('/\d{4}\-\d{2}\-\d{2}/', $mystring, $matches);
print_r($matches);
print("\nlast match: \n");
print_r($matches[0][count($matches[0])-1]);
print("\n");
?>
Prints the whole object returned and the last match:
Array
(
[0] => Array
(
[0] => 2010-01-01
[1] => 2016-12-12
)
)
last match:
2016-12-12
Related
I am searching a line using preg_match_all, but it is not known exactly what this line will look like. For example, it could look like this:
XXX012-013-015-######
Or it could look like this:
XXX012-013-015-XXX001-002-######
Where the 'X's are any letter and the '#'s are any number.
This is the relevant portion of the preg_match_all code that works exactly as expected if the line was always setup like the first example:
if (preg_match_all('([A-Z]{3})((?:[0-9]{3}[->]{1}){1,32})([0-9]{2})([0-9]{2})([0-9]{2})...rest of code...#', $wwalist, $matches)) {
$wwaInfo['locationabbrev'][$wwanum] = $matches[2][$keys[$wwanum]];
}
The $matches[2] will display "012-013-015" as expected. Since the first part, xxx012-013-015, can repeat, I need for the preg_match_all $matches[2] to display the following if it is run on the second example:
012-013-015-001-002
This was my attempt, but it does not work:
if (preg_match_all('#([A-Z]{3})((?:[0-9]{3}[->]{1}){1,32})((?:[A-Z]{3}){0,1})(?:((?:[0-9]{3}[->]{1}){1,3}){0,3})([0-9]{2})([0-9]{2})([0-9]{2})...rest of code...#', $wwalist, $matches)) {
Hopefully this makes sense. Any help would be much appreciated! Thanks!
You aren't going to be able to match and join matches in the same step.
Will this work for you:
Code: (Pattern Demo) (PHP Demo)
$strings=[
'ABC012-013-015-XYZ001-002-345435',
'ABC012-013-015-345453',
'XYZ013-014-015-016-EFG017-123456'
];
foreach($strings as $s){
if(preg_match('/[A-Z]{3}\d{3}/',$s)){ // check if string qualifies
echo 'Match found. Prepared string: ';
$s=preg_replace('/([A-Z]{3}|-\d{6})/','',$s); // remove unwanted substrings
echo "$s\n";
}
}
Output:
Match found. Prepared string: 012-013-015-001-002
Match found. Prepared string: 012-013-015
Match found. Prepared string: 013-014-015-016-017
You could use a replace call and then output a new string with the matches, so for example:
ABC012-013-015-XYZ001-002-345435
ABC012-013-015-345453
XYZ013-014-015-016-EFG017-123456
$rep = preg_replace( '/(?mi-Us)([^0-9-\n]{3,})|-[0-9]{4,}/', '', $str) ;
echo ( $rep );
Should result in:
012-013-015-001-002
012-013-015
013-014-015-016-017
To output to an array:
$mat = preg_match_all( '/([0-9-]+)\n/', $rep, $res) ;
print_r( $res[1] ) ;
foreach( $res[1] as $result ) {
echo $result . "\n" ;
}
For the code you've shown you could probably do:
$rep = preg_replace( '/(?mi-Us)([^0-9-\n]{3,})|-[0-9]{4,}/', '', $wwalist ) ;
if (preg_match_all('/([0-9-]+)\n/', $rep, $matches)) {
$wwaInfo['locationabbrev'][$wwanum] = $matches[1][$keys[$wwanum]];
print_r( $wwaInfo['locationabbrev'][$wwanum] ); // comment out when done testing
}
Which should return the array:
Array
(
[0] => 012-013-015-001-002
[1] => 012-013-015
[2] => 013-014-015-016-017
)
i know that its easy to extract string between two slashes using explode() function in php, What if the string is like
localhost/used_cars/search/mk_honda/md_city/mk_toyota
i want to extract string after mk_ and till the slashes like:** honda,toyota **
any help would be highly appreciated.
I am doing like this
echo strpos(uri_string(),'mk') !== false ? $arr = explode("/", $string, 2);$first = $arr[0]; : '';
but not working because if user enter mk_honda in any position then explode() is failed to handle that.
Use regex:
http://ideone.com/DNHXsf
<?php
$input = 'localhost/used_cars/search/mk_honda/md_city/mk_toyota';
preg_match_all('#/mk_([^/]*)#', $input, $matches);
print_r($matches[1]);
?>
Output:
Array
(
[0] => honda
[1] => toyota
)
Explode your string by /, then check every element of array with strpos:
$string = 'localhost/used_cars/search/mk_honda/md_city/mk_toyota';
$parts = explode('/', $string);
$r = [];
foreach ($parts as $p) {
// use `===` as you need `mk_` in position 0
if (strpos($p, 'mk_') === 0) {
// 3 is a length of `mk_`
$r[] = substr($p, 3);
}
}
echo'<pre>',print_r($r),'</pre>';
Just try this
$str='localhost/used_cars/search/mk_honda/md_city/mk_toyota';
$str=explode('/',$str);
$final=[];
foreach ($str as $words){
(!empty(explode('_',$words)))?(isset(explode('_',$words)[1]))?$final[]=explode('_',$words)[1]:false:false;
}
$final=implode(',',$final);
echo $final;
It give output as
cars,honda,city,toyota
I am trying to get the integer on the left and right for an input from the $str variable using REGEX. But I keep getting the commas back along with the integer. I only want integers not the commas. I have also tried replacing the wildcard . with \d but still no resolution.
$str = "1,2,3,4,5,6";
function pagination()
{
global $str;
// Using number 4 as an input from the string
preg_match('/(.{2})(4)(.{2})/', $str, $matches);
echo $matches[0]."\n".$matches[1]."\n".$matches[1]."\n".$matches[1]."\n";
}
pagination();
How about using a CSV parser?
$str = "1,2,3,4,5,6";
$line = str_getcsv($str);
$target = 4;
foreach($line as $key => $value) {
if($value == $target) {
echo $line[($key-1)] . '<--low high-->' . $line[($key+1)];
}
}
Output:
3<--low high-->5
or a regex could be
$str = "1,2,3,4,5,6";
preg_match('/(\d+),4,(\d+)/', $str, $matches);
echo $matches[1]."<--low high->".$matches[2];
Output:
3<--low high->5
The only flaw with these approaches is if the number is the start or end of range. Would that ever be the case?
I believe you're looking for Regex Non Capture Group
Here's what I did:
$regStr = "1,2,3,4,5,6";
$regex = "/(\d)(?:,)(4)(?:,)(\d)/";
preg_match($regex, $regStr, $results);
print_r($results);
Gives me the results:
Array ( [0] => 3,4,5 [1] => 3 [2] => 4 [3] => 5 )
Hope this helps!
Given your function name I am going to assume you need this for pagination.
The following solution might be easier:
$str = "1,2,3,4,5,6,7,8,9,10";
$str_parts = explode(',', $str);
// reset and end return the first and last element of an array respectively
$start = reset($str_parts);
$end = end($str_parts);
This prevents your regex from having to deal with your numbers getting into the double digits.
I am trying to make a php script to output all values inside an hypehref=" ** " from a text file.
I'm having a hard time with the regular expression part.
This is what I have
$Vdata = file_get_contents('file.txt');
preg_match( '/hyperef="(.*?)"/', $Vdata, $match );
echo '<pre>'; print_r($match); echo '</pre>'
My result is this :
Array
(
[0] => hyperef="http://lookbook.nu/look/5709720-Choies-Silvery-Bag-Rosewholesale-Punk-Style/hype"
[1] => http://lookbook.nu/look/5709720-Choies-Silvery-Bag-Rosewholesale-Punk-Style/hype
)
The [0] is incorrect, it includes the part I am searching for... all I want is the result after the hypehref="
The second result [1] is correct
and my file should have given me about 10 results.. not just 2...
Any ideas why ? Thx
You can use preg_match_all to find all matches. There you will also have the full part and only the value of the hyperef - but you can only use the former.
if (preg_match_all('/hyperef="(.*?)"/i', $Vdata, $result)) {
$matches = $result[1]; //only values inside quotation marks
print_r($matches);
} else
print "nothing found";
I added the if for obvious reasons and the i delimiter, so the pattern will ignore case sensitivity.
$pattern = "/\bo'reilly\b/i"; // only O'Reilly
$ora_books = preg_grep($pattern, file('filed.txt'));
var_dump($ora_books);
example 2
$fh = fopen('/path/to/your/file.txt', 'r') or die($php_errormsg);
while (!feof($fh)) {
$line = fgets($fh);
if (preg_match($pattern, $line)) { $ora_books[ ] = $line; }
}
fclose($fh);
Say I have a string like this:
$string = '.30..5..12..184..6..18..201..1.'
How would I pull out each of the integers, stripping the periods, and store them into an array?
You could use this. You break the string up by all of the periods... but this only works if it is exactly like that; if there is other stuff in the middle for example 25.sdg.12 it wouldnt work.
<?php
$my_array = explode("..",$string);
$my_array[0] = trim($my_array[0]); //This removes the period in first part making '.30' into '30'
///XXX $my_array[-1] = trim($my_array[-1]); XXX If your string is always the same format as that you could just use 7 instead.
I checked and PHP doesn't support negative indexes but you can count the array list and just use that. Ex:
$my_index = count($my_array) - 1;
$my_array[$my_index] = trim($my_array[$my_index]); //That should replace '1.' with '1' no matter what format or length your string is.
?>
This will break up your string into an array and then loop through to grab numbers.
$string = '.30..5..12..184..6..18..201..1.';
$pieces = explode('.', $string);
foreach($pieces as $key=>$val) {
if( is_numeric($val) ) {
$numbers[] = $val;
}
}
Your numbers will be in the array $numbers
All I could think of.
<?php
$string = '.30..5..12..184..6..18..201..1.';
$r_string = str_replace("..", ",", $string);
$r_string = str_replace(".", ",", $r_string);
print_r(explode(",", $r_string));
?>
Or If you want to the array in a variable
<?php
$string = '.30..5..12..184..6..18..201..1.';
$r_string = str_replace("..", ",", $string);
$r_string = str_replace(".", ",", $r_string);
$arr_ex = explode(",", $r_string);
print_r($arr_ex);
?>
Someone else posted this but then removed their code, it works as intended:
<?php
$string = '.30..5..12..184..6..18..201..1.';
$numbers = array_filter (explode ('.', $string), 'is_numeric');
print_r ($numbers);
?>
Output:
Array (
[1] => 30
[3] => 5
[5] => 12
[7] => 184
[9] => 6
[11] => 18
[13] => 201
[15] => 1 )
try this ..
$string = '.30..5..12..184..6..18..201..1.';
$new_string =str_replace(".", "", str_replace("..", ",", $string));
print_r (explode(",",$new_string));
One line solution:
print_r(explode("..",substr($string,1,-1)));