I need to parse an HTML document and to find all occurrences of string asdf in it.
I currently have the HTML loaded into a string variable. I would just like the character position so I can loop through the list to return some data after the string.
The strpos function only returns the first occurrence. How about returning all of them?
Without using regex, something like this should work for returning the string positions:
$html = "dddasdfdddasdffff";
$needle = "asdf";
$lastPos = 0;
$positions = array();
while (($lastPos = strpos($html, $needle, $lastPos))!== false) {
$positions[] = $lastPos;
$lastPos = $lastPos + strlen($needle);
}
// Displays 3 and 10
foreach ($positions as $value) {
echo $value ."<br />";
}
You can call the strpos function repeatedly until a match is not found. You must specify the offset parameter.
Note: in the following example, the search continues from the next character instead of from the end of previous match. According to this function, aaaa contains three occurrences of the substring aa, not two.
function strpos_all($haystack, $needle) {
$offset = 0;
$allpos = array();
while (($pos = strpos($haystack, $needle, $offset)) !== FALSE) {
$offset = $pos + 1;
$allpos[] = $pos;
}
return $allpos;
}
print_r(strpos_all("aaa bbb aaa bbb aaa bbb", "aa"));
Output:
Array
(
[0] => 0
[1] => 1
[2] => 8
[3] => 9
[4] => 16
[5] => 17
)
Its better to use substr_count . Check out on php.net
function getocurence($chaine,$rechercher)
{
$lastPos = 0;
$positions = array();
while (($lastPos = strpos($chaine, $rechercher, $lastPos))!== false)
{
$positions[] = $lastPos;
$lastPos = $lastPos + strlen($rechercher);
}
return $positions;
}
This can be done using strpos() function. The following code is implemented using for loop. This code is quite simple and pretty straight forward.
<?php
$str_test = "Hello World! welcome to php";
$count = 0;
$find = "o";
$positions = array();
for($i = 0; $i<strlen($str_test); $i++)
{
$pos = strpos($str_test, $find, $count);
if($pos == $count){
$positions[] = $pos;
}
$count++;
}
foreach ($positions as $value) {
echo '<br/>' . $value . "<br />";
}
?>
Use preg_match_all to find all occurrences.
preg_match_all('/(\$[a-z]+)/i', $str, $matches);
For further reference check this link.
Salman A has a good answer, but remember to make your code multibyte-safe. To get correct positions with UTF-8, use mb_strpos instead of strpos:
function strpos_all($haystack, $needle) {
$offset = 0;
$allpos = array();
while (($pos = mb_strpos($haystack, $needle, $offset)) !== FALSE) {
$offset = $pos + 1;
$allpos[] = $pos;
}
return $allpos;
}
print_r(strpos_all("aaa bbb aaa bbb aaa bbb", "aa"));
Another solution is to use explode():
public static function allSubStrPos($str, $del)
{
$searchArray = explode($del, $str);
unset($searchArray[count($searchArray) - 1]);
$positionsArray = [];
$index = 0;
foreach ($searchArray as $i => $s) {
array_push($positionsArray, strlen($s) + $index);
$index += strlen($s) + strlen($del);
}
return $positionsArray;
}
Simple strpos_all() function.
function strpos_all($haystack, $needle_regex)
{
preg_match_all('/' . $needle_regex . '/', $haystack, $matches, PREG_OFFSET_CAPTURE);
return array_map(function ($v) {
return $v[1];
}, $matches[0]);
}
Usage:
Simple string as needle.
$html = "dddasdfdddasdffff";
$needle = "asdf";
$all_positions = strpos_all($html, $needle);
var_dump($all_positions);
Output:
array(2) {
[0]=>
int(3)
[1]=>
int(10)
}
Or with regex as needle.
$html = "dddasdfdddasdffff";
$needle = "[d]{3}";
$all_positions = strpos_all($html, $needle);
var_dump($all_positions);
Output:
array(2) {
[0]=>
int(0)
[1]=>
int(7)
}
<?php
$mainString = "dddjmnpfdddjmnpffff";
$needle = "jmnp";
$lastPos = 0;
$positions = array();
while (($lastPos = strpos($html, $needle, $lastPos))!== false) {
$positions[] = $lastPos;
$lastPos = $lastPos + strlen($needle);
}
// Displays 3 and 10
foreach ($positions as $value) {
echo $value ."<br />";
}
?>
Related
I'm trying to do some sort of translator which would be able to keep text uppercase/lowercase.
I need to replace it in PHP string and MySQL query too.
Example:
Potato is jumping all over the PLACE.
Potato is jumping all over the pLAcE. (optional)
Potato is jumping all over the place.
Potato is jumping all over the Place.
I want to replace word 'place' with 'garden'.
Potato is jumping all over the GARDEN.
Potato is jumping all over the gARdEe. (optional)
Potato is jumping all over the garden.
Potato is jumping all over the Garden.
It should also work with phrases.
I've created a function that will replace the word for you and keep the cases.
function replaceWithCase($source, $replacement, $string) {
// Does the string contain the source word?
if (strpos($string, $source) === false) {
return false;
}
// If everything is uppercase, return the replacement fully uppercase
if (ctype_upper($source)) {
return str_replace($source, strtoupper($replacement));
}
// Set an array to work with
$characters = array();
// Split the source into characters
$sourceParts = explode('', $source);
// Loop throug the characters and set the case
foreach ($sourceParts as $k => $sp) {
if (ctype_upper($sp)) {
$characters[$k] = true;
} else {
$characters[$k] = false;
}
}
// Split the replacement into characters
$replacementParts = explode('', $replacement);
// Loop through characters and compare their case type
foreach ($replacementParts as $k => $rp) {
if (array_key_exists($k, $characters) && $characters[$k] === true) {
$newWord[] = strtoupper($rp);
} else {
$newWord[] = strtolower($rp);
}
}
return substr_replace($source, implode('', $newWord), $string);
}
// usage
echo replaceWithCase('AppLes', 'bananas', 'Comparing AppLes to pears');
Note: it is untested and might need some tweaking
function stringReplace($findStr, $replaceStr, $str)
{
$isLowerStr = true;
for($i=0; $i<strlen($findStr); $i++){
if(ord($findStr[$i]) >= 97 && ord($findStr[$i])<=122){
if(ord($replaceStr[$i]) >= 65 && ord($replaceStr[$i])<=96){
$replaceStr[$i] = strtolower($replaceStr[$i]);
}else{
$replaceStr[$i] = $replaceStr[$i];
}
}else{
$isLowerStr = false;
$replaceStr[$i] = strtoupper($replaceStr[$i]);
}
}
if($isLowerStr == false){
if(strlen($replaceStr) > strlen($findStr)){
for($i=0;$i<(strlen($replaceStr)-strlen($findStr));$i++){
if(strtoupper($findStr) == $findStr){
$replaceStr[strlen($findStr)+$i] = strtoupper($replaceStr[strlen($findStr)+$i]);
}else{
$replaceStr[strlen($findStr)+$i] = strtolower($replaceStr[strlen($findStr)+$i]);
}
}
}
}
echo str_replace($findStr, $replaceStr, $str);die;
}
$findStr = 'Place';
$replaceStr = 'garden';
echo stringReplace($findStr, $replaceStr, 'Potato is jumping all over the '.$findStr.'.');
So I managed to create my own function in the end. Thanks for help and inspiration though.
function replaceWithCase($source, $replacement, $string, $pos = 0) {
while (($pos = strpos(strtolower($string), strtolower($source), $pos))!== false) {
$substr = mb_substr($string, $pos, strlen($source));
$remaining = mb_substr($string, $pos + strlen($source));
if (ctype_upper($substr)) {
$string = substr_replace($string,strtoupper($replacement),$pos,strlen($source));
continue;
}
$substrParts = preg_split('//u', $substr, null, PREG_SPLIT_NO_EMPTY);
$replaceParts = preg_split('//u', $replacement, null, PREG_SPLIT_NO_EMPTY);
$newWord = '';
foreach ($replaceParts as $k => $rp) {
if (array_key_exists($k,$substrParts))
$newWord .= ctype_upper($substrParts[$k]) ? mb_strtoupper($rp) : mb_strtolower($rp);
else
$newWord .= $rp;
}
$string = substr_replace($string,$newWord,$pos,strlen($source));
$pos = $pos + strlen($source);
}
return $string;
}
echo replaceWithCase("place", "garden", "Potato is jumping all over the PLACE");
echo "<br>";
echo replaceWithCase("jumping", "running", "Potato is jumping all over the pLAcE");
echo "<br>";
echo replaceWithCase("jumping", "cry", "Potato is jumping all over the place");
echo "<br>";
echo replaceWithCase("all", "", "Potato is jumping all over the Place");
echo "<br>";
echo replaceWithCase(" ", ";", "Potato is jumping all over the Place", 10);
echo "<br>";
Output:
Potato is jumping all over the GARDEN
Potato is running all over the pLAcE
Potato is cry all over the place
Potato is jumping over the Place
Potato is jumping;all;over;the;Place
Thanks #LadaB - that's a really helpful function but it also replaces partial word matches. Sometimes you might want this, but in others cases you won't, for example if you have:
$source = 'mom';
$replacement = 'mum'; // british spelling of "mom"
$string = 'Be in the moment with your Mom.';
You get: "Be in the mument with your Mum."
So, I have added an option to make the match "whole word only".
I found another issue where multibyte characters would shift where the capitalization ended up, which seems to be fixed by changing. mb_substr to substr.
I also removed the unused:
$remaining = substr($string, $pos + strlen($source));
My latest (I think fully working) version is:
function replaceWithCase($source, $replacement, $string, $wholeWordOnly = false) {
$pos = 0;
while (($pos = strpos(strtolower($string), strtolower($source), $pos))!== false) {
if($wholeWordOnly) {
preg_match("/\b".$string[$pos]."/", $string[($pos-1)] . $string[$pos], $start);
preg_match("/".$string[($pos+strlen($source)-1)]."\b/", $source . $string[($pos+strlen($source))], $end);
}
if(($wholeWordOnly && $start && $end) || !$wholeWordOnly) {
$substr = substr($string, $pos, strlen($source));
if (ctype_upper($substr)) {
$string = substr_replace($string,strtoupper($replacement),$pos,strlen($source));
continue;
}
$substrParts = preg_split('//u', $substr, -1, PREG_SPLIT_NO_EMPTY);
$replaceParts = preg_split('//u', $replacement, -1, PREG_SPLIT_NO_EMPTY);
$newWord = '';
foreach ($replaceParts as $k => $rp) {
if (array_key_exists($k,$substrParts))
$newWord .= ctype_upper($substrParts[$k]) ? mb_strtoupper($rp) : mb_strtolower($rp);
else
$newWord .= $rp;
}
$string = substr_replace($string,$newWord,$pos,strlen($source));
}
$pos = $pos + strlen($source);
}
return $string;
}
Hope that helps you or someone else.
Use "stripos" php function
$str = 'Potato is jumping all over the pLAcEs.';
$str_new = "garden";
$str1 = str_split($str_new);
$pos = stripos($str,'places');
$string = substr($str,$pos,6);
$extrct = str_split($string);
$var = '';
foreach ($extrct as $key => $value) {
if(ctype_upper($value))
{
$var .= strtoupper($str1[$key]);
}else{
$var .= strtolower($str1[$key]);
}
}
$new_string = str_replace($string, $var, $str);
echo $new_string; //Potato is jumping all over the gARdEn.
I am making a website that displays backup information.
The obstacle that I'm getting is that I need to get info before a certain character position.
String looks like:
Data1 => 2019-06-30-08-00-00 , 2019-07-30-08-00-00 , 2019-08-30-08-00-00 Data2 => 2019-06-30-08-30-00 , 2019-07-30-08-30-00 , 2019-08-30-08-30-00
My code for getting all search info from string.
$BackupJob_list = $BackupJob_list['Data'];
$BackupJob_list = json_encode($BackupJob_list);
$string = "$BackupJob_list"; //String where I need the info from
$needle = "2019-08-30"; //The search value
$lastPos = 0; //Starting position
$positions = array();
//Get lastPos and go again...
while (($lastPos = strpos($string, $needle, $lastPos))!== false) {
$positions[] = $lastPos;
$lastPos = $lastPos + strlen($needle);
}
//Echo every value that is found in the string.
foreach ($positions as $value) {
echo substr($BackupJob_list, $value, 19)."<br/>";
}
What I'm trying to get is:
2019-06-30-08-00-00
Now I'm getting
2019-06-30-08-00-00
2019-06-30-08-30-00
You can use strpos (doc) to check that as:
$str = "2019-06-30-08-00-00,2019-07-30-08-00-00,2019-08-30-08-00-00";
$needle = "2019-08-30";
$arr = explode(",", $str); // convert string to array
foreach($arr as $e) {
if (strpos($e, $needle) === 0) echo "Found! Here: $e \n";
}
I'm trying to do some sort of translator which would be able to keep text uppercase/lowercase.
I need to replace it in PHP string and MySQL query too.
Example:
Potato is jumping all over the PLACE.
Potato is jumping all over the pLAcE. (optional)
Potato is jumping all over the place.
Potato is jumping all over the Place.
I want to replace word 'place' with 'garden'.
Potato is jumping all over the GARDEN.
Potato is jumping all over the gARdEe. (optional)
Potato is jumping all over the garden.
Potato is jumping all over the Garden.
It should also work with phrases.
I've created a function that will replace the word for you and keep the cases.
function replaceWithCase($source, $replacement, $string) {
// Does the string contain the source word?
if (strpos($string, $source) === false) {
return false;
}
// If everything is uppercase, return the replacement fully uppercase
if (ctype_upper($source)) {
return str_replace($source, strtoupper($replacement));
}
// Set an array to work with
$characters = array();
// Split the source into characters
$sourceParts = explode('', $source);
// Loop throug the characters and set the case
foreach ($sourceParts as $k => $sp) {
if (ctype_upper($sp)) {
$characters[$k] = true;
} else {
$characters[$k] = false;
}
}
// Split the replacement into characters
$replacementParts = explode('', $replacement);
// Loop through characters and compare their case type
foreach ($replacementParts as $k => $rp) {
if (array_key_exists($k, $characters) && $characters[$k] === true) {
$newWord[] = strtoupper($rp);
} else {
$newWord[] = strtolower($rp);
}
}
return substr_replace($source, implode('', $newWord), $string);
}
// usage
echo replaceWithCase('AppLes', 'bananas', 'Comparing AppLes to pears');
Note: it is untested and might need some tweaking
function stringReplace($findStr, $replaceStr, $str)
{
$isLowerStr = true;
for($i=0; $i<strlen($findStr); $i++){
if(ord($findStr[$i]) >= 97 && ord($findStr[$i])<=122){
if(ord($replaceStr[$i]) >= 65 && ord($replaceStr[$i])<=96){
$replaceStr[$i] = strtolower($replaceStr[$i]);
}else{
$replaceStr[$i] = $replaceStr[$i];
}
}else{
$isLowerStr = false;
$replaceStr[$i] = strtoupper($replaceStr[$i]);
}
}
if($isLowerStr == false){
if(strlen($replaceStr) > strlen($findStr)){
for($i=0;$i<(strlen($replaceStr)-strlen($findStr));$i++){
if(strtoupper($findStr) == $findStr){
$replaceStr[strlen($findStr)+$i] = strtoupper($replaceStr[strlen($findStr)+$i]);
}else{
$replaceStr[strlen($findStr)+$i] = strtolower($replaceStr[strlen($findStr)+$i]);
}
}
}
}
echo str_replace($findStr, $replaceStr, $str);die;
}
$findStr = 'Place';
$replaceStr = 'garden';
echo stringReplace($findStr, $replaceStr, 'Potato is jumping all over the '.$findStr.'.');
So I managed to create my own function in the end. Thanks for help and inspiration though.
function replaceWithCase($source, $replacement, $string, $pos = 0) {
while (($pos = strpos(strtolower($string), strtolower($source), $pos))!== false) {
$substr = mb_substr($string, $pos, strlen($source));
$remaining = mb_substr($string, $pos + strlen($source));
if (ctype_upper($substr)) {
$string = substr_replace($string,strtoupper($replacement),$pos,strlen($source));
continue;
}
$substrParts = preg_split('//u', $substr, null, PREG_SPLIT_NO_EMPTY);
$replaceParts = preg_split('//u', $replacement, null, PREG_SPLIT_NO_EMPTY);
$newWord = '';
foreach ($replaceParts as $k => $rp) {
if (array_key_exists($k,$substrParts))
$newWord .= ctype_upper($substrParts[$k]) ? mb_strtoupper($rp) : mb_strtolower($rp);
else
$newWord .= $rp;
}
$string = substr_replace($string,$newWord,$pos,strlen($source));
$pos = $pos + strlen($source);
}
return $string;
}
echo replaceWithCase("place", "garden", "Potato is jumping all over the PLACE");
echo "<br>";
echo replaceWithCase("jumping", "running", "Potato is jumping all over the pLAcE");
echo "<br>";
echo replaceWithCase("jumping", "cry", "Potato is jumping all over the place");
echo "<br>";
echo replaceWithCase("all", "", "Potato is jumping all over the Place");
echo "<br>";
echo replaceWithCase(" ", ";", "Potato is jumping all over the Place", 10);
echo "<br>";
Output:
Potato is jumping all over the GARDEN
Potato is running all over the pLAcE
Potato is cry all over the place
Potato is jumping over the Place
Potato is jumping;all;over;the;Place
Thanks #LadaB - that's a really helpful function but it also replaces partial word matches. Sometimes you might want this, but in others cases you won't, for example if you have:
$source = 'mom';
$replacement = 'mum'; // british spelling of "mom"
$string = 'Be in the moment with your Mom.';
You get: "Be in the mument with your Mum."
So, I have added an option to make the match "whole word only".
I found another issue where multibyte characters would shift where the capitalization ended up, which seems to be fixed by changing. mb_substr to substr.
I also removed the unused:
$remaining = substr($string, $pos + strlen($source));
My latest (I think fully working) version is:
function replaceWithCase($source, $replacement, $string, $wholeWordOnly = false) {
$pos = 0;
while (($pos = strpos(strtolower($string), strtolower($source), $pos))!== false) {
if($wholeWordOnly) {
preg_match("/\b".$string[$pos]."/", $string[($pos-1)] . $string[$pos], $start);
preg_match("/".$string[($pos+strlen($source)-1)]."\b/", $source . $string[($pos+strlen($source))], $end);
}
if(($wholeWordOnly && $start && $end) || !$wholeWordOnly) {
$substr = substr($string, $pos, strlen($source));
if (ctype_upper($substr)) {
$string = substr_replace($string,strtoupper($replacement),$pos,strlen($source));
continue;
}
$substrParts = preg_split('//u', $substr, -1, PREG_SPLIT_NO_EMPTY);
$replaceParts = preg_split('//u', $replacement, -1, PREG_SPLIT_NO_EMPTY);
$newWord = '';
foreach ($replaceParts as $k => $rp) {
if (array_key_exists($k,$substrParts))
$newWord .= ctype_upper($substrParts[$k]) ? mb_strtoupper($rp) : mb_strtolower($rp);
else
$newWord .= $rp;
}
$string = substr_replace($string,$newWord,$pos,strlen($source));
}
$pos = $pos + strlen($source);
}
return $string;
}
Hope that helps you or someone else.
Use "stripos" php function
$str = 'Potato is jumping all over the pLAcEs.';
$str_new = "garden";
$str1 = str_split($str_new);
$pos = stripos($str,'places');
$string = substr($str,$pos,6);
$extrct = str_split($string);
$var = '';
foreach ($extrct as $key => $value) {
if(ctype_upper($value))
{
$var .= strtoupper($str1[$key]);
}else{
$var .= strtolower($str1[$key]);
}
}
$new_string = str_replace($string, $var, $str);
echo $new_string; //Potato is jumping all over the gARdEn.
<?php
$randomstring = 'raabccdegep';
$arraylist = array("car", "egg", "total");
?>
Above $randomstring is a string which contain some alphabet letters.
And I Have an Array called $arraylist which Contain 3 Words Such as 'car' , 'egg' , 'total'.
Now I need to check the string Using the words in array and print if the word can be created using the string.
For Example I need an Output Like.
car is possible.
egg is not possible.
total is not possible.
Also Please Check the repetition of letter. ie, beep is also possible. Because the string contains two e. But egg is not possible because there is only one g.
function find_in( $haystack, $item ) {
$match = '';
foreach( str_split( $item ) as $char ) {
if ( strpos( $haystack, $char ) !== false ) {
$haystack = substr_replace( $haystack, '', strpos( $haystack, $char ), 1 );
$match .= $char;
}
}
return $match === $item;
}
$randomstring = 'raabccdegep';
$arraylist = array( "beep", "car", "egg", "total");
foreach ( $arraylist as $item ) {
echo find_in( $randomstring, $item ) ? " $item found in $randomstring." : " $item not found in $randomstring.";
}
This should do the trick:
<?php
$randomstring = 'raabccdegep';
$arraylist = array("car", "egg", "total");
foreach($arraylist as $word){
$checkstring = $randomstring;
$beMade = true;
for( $i = 0; $i < strlen($word); $i++ ) {
$char = substr( $word, $i, 1 );
$pos = strpos($checkstring, $char);
if($pos === false){
$beMade = false;
} else {
substr_replace($checkstring, '', $i, 1);
}
}
if ($beMade){
echo $word . " is possible \n";
} else {
echo $word . " is not possible \n";
}
}
?>
I want to get the position of 'ja' in each of the words in $string, but its not working. what am i doing wrong?
<?php
$offset = 0;
$find = 'ja';
$find_length = strlen($find);
$string = 'jasim jasmin jassir';
while ($string_position = strpos($string, $find, $offer)) {
echo $find.' found at '.$string_position.'<br>';
$offset = $string_position + $find_length;
}
?>
Change the variable name to $offset
strpos may return 0 and while will treat it as false
So replace your while statement with:
while (($string_position = strpos($string, $find, $offset)) !== false) {
<?php
// stack overflow area
$offset = 0;
$find = 'ja';
$find_length = strlen($find);
$string = 'jasim jasmin jassir';
if (strpos($string, $find) === false) {
echo "not found";
}
else {
while (strpos($string, $find, $offset) !== false) {
$string_position = strpos($string, $find, $offset);
echo $find.' found at '.$string_position.'<br>';
$offset = $string_position + $find_length;
}
}
?>
Little workaround, but it apparently works.
Output:
ja found at 0
ja found at 6
ja found at 13
try changing offest
<?php
$offset = 1;
$find = 'ja';
$find_length = strlen($find);
$string = 'jasim jasmin jassir';
while ($string_position = strpos($string, $find, $offset)) {
echo $find.' found at '.$string_position.'<br>';
$offset = $string_position + $find_length;
}
?>
// output :- ja found at 6
ja found at 13
if you don't want to change offset use
$string = ' jasim jasmin jassir'; (without space not be jasim it's 'jasim )
then it will output 3
ja found at 1
ja found at 7
ja found at 14
OR try to change your condition check
while (($string_position = strpos($string, $find, $offset)) !== false) {
Probably you should code this way to find string positions
$positions = array();
$offset = -1;
while (($pos = strpos($string, $find, $offset+1)) !== false) {
$positions[] = $offset;
}
$result = implode(', ', $positions);
print this result