replace all matches in string after given position without regular expressions - php

I have a string abcxdefxghix. I wish to remove all "x"s except the first one. I can easily find the position of the first "x" using strpos(), so wish to remove all "x"s after that position. str_replace() performs a replacement of a given string with another, but doesn't allow a start position. substr_replace() gives a start position, but doesn't have the search parameter. I realize this can be done using preg_replace() but it seems like it should also be possible with without regular expressions (or without some crazy split/replace/assemble strategy).

You could do something like this:
list($first,$remainder) = explode($searchString,$subjectString,2);
$remainder = str_replace($searchString,$replacementString,$remainder);
$resultString = $first.$searchString.$remainder;

I 'd most likely do it the old-fashioned way:
$index = strpos($input, $needle);
if ($index !== false) {
$input = substr($input, 0, $index + 1).
str_replace($needle, $replacement, substr($input, $index + 1));
}

I thought there had to be an easier way, but evidently there isn't. My homespun function was negligently faster, but if there is an "old-fashion way", it is probably the way to go.
function replace_all_but_first_1($search,$replace,$subject){
$pos=strpos($subject,$search);
return ($pos===false)?$subject:substr($subject,0,$pos+1).str_replace($search,$replace,substr($subject, $pos));
}
function replace_all_but_first_2($search,$replace,$subject){
$index = strpos($subject, $search);
if ($index !== false) {
$subject = substr($subject, 0, $index + 1).
str_replace($search, $replace, substr($subject, $index + 1));
}
return $subject;
}
function replace_all_but_first_3($search,$replace,$subject){
list($first,$remainder) = explode($search,$subject,2);
$remainder = str_replace($search,$replace,$remainder);
$resultString = $first.$search.$remainder;
return $resultString;
}
function replace_all_but_first($search,$replace,$subject){
echo('Replace "'.$search.'" with "'.$replace.'" in "'.$subject.'"<br><br>');
echo('replace_all_but_first_1: '.replace_all_but_first_1($search,$replace,$subject)."<br>");
echo('replace_all_but_first_2: '.replace_all_but_first_2($search,$replace,$subject)."<br>");
echo('replace_all_but_first_3: '.replace_all_but_first_3($search,$replace,$subject)."<br>");
$time=microtime(true);
for ($i = 1; $i <= 100000; $i++) {$x=replace_all_but_first_1($search,$replace,$subject);}
echo('replace_all_but_first_1 '.(microtime(true)-$time).'<br>');
$time=microtime(true);
for ($i = 1; $i <= 100000; $i++) {$x=replace_all_but_first_2($search,$replace,$subject);}
echo('replace_all_but_first_2 '.(microtime(true)-$time).'<br>');
$time=microtime(true);
for ($i = 1; $i <= 100000; $i++) {$x=replace_all_but_first_3($search,$replace,$subject);}
echo('replace_all_but_first_3 '.(microtime(true)-$time).'<br>');
echo('<br><br><br>');
}
replace_all_but_first('x','','abcxdefxghix');
replace_all_but_first('x','','xabcxdefxghix');
replace_all_but_first('z','','abcxdefxghix');
Replace "x" with "" in "abcxdefxghix"
replace_all_but_first_1: abcxdefghi
replace_all_but_first_2: abcxdefghi
replace_all_but_first_3: abcxdefghi
replace_all_but_first_1 0.18973803520203
replace_all_but_first_2 0.19031405448914
replace_all_but_first_3 0.19151902198792
Replace "x" with "" in "xabcxdefxghix"
replace_all_but_first_1: xabcdefghi
replace_all_but_first_2: xabcdefghi
replace_all_but_first_3: xabcdefghi
replace_all_but_first_1 0.18725895881653
replace_all_but_first_2 0.19358086585999
replace_all_but_first_3 0.19228482246399
Replace "z" with "" in "abcxdefxghix"
replace_all_but_first_1: abcxdefxghix
replace_all_but_first_2: abcxdefxghix
replace_all_but_first_3: abcxdefxghixz
replace_all_but_first_1 0.074465036392212
replace_all_but_first_2 0.075581073760986
replace_all_but_first_3 0.71253705024719

Related

Reverse string without strrev

Some time ago during a job interview I got the task to reverse a string in PHP without using strrev.
My first solution was something like this:
$s = 'abcdefg';
$temp = '';
for ($i = 0, $length = mb_strlen($s); $i < $length; $i++) {
$temp .= $s{$length - $i - 1};
}
var_dump($temp);
// outputs string(7) "gfedcba"
then they asked me if I could do this without doubling the memory usage (not using the $temp variable or any variable to copy the reversed string to) and I failed.
This kept bugging me and since then I tried to solve this multiple times but I constantly failed.
My latest try looks like this:
$s = 'abcdefg';
for ($i = 0, $length = mb_strlen($s); $i < $length; $i++) {
$s = $s{$i * 2} . $s;
}
var_dump($s);
// outputs string(14) "gfedcbaabcdefg"
It's not a solution to chop off "abcdefg" after the loop because then I would still double the amount of memory used. I need to remove the last character in every iteration of the loop.
I tried to use mb_substr like this:
$s = 'abcdefg';
for ($i = 0, $length = mb_strlen($s); $i < $length; $i++) {
$s = $s{$i * 2} . mb_substr($s, $length - $i - 1, 1);
}
var_dump($s);
but it only gives me Uninitialized string offset errors.
This is where I'm stuck (again). I tried googling but all the solutions I found either echo the characters directly or use a temporary variable.
I also found the Question PHP String reversal without using extra memory but there's no answer that fits my needs.
That's an interesting one.
Here's something I just came up with:
$s = 'abcdefghijklm';
for($i=strlen($s)-1, $j=0; $j<$i; $i--, $j++) {
list($s[$j], $s[$i]) = array($s[$i], $s[$j]);
}
echo $s;
list() can be used to assign a list of variables in one operation. So what I am doing is simply swapping characters (starting with first and last, then second-first and second-last and so on, till it reaches the middle of the string)
Output is mlkjihgfedcba.
Not using any other variables than $s and the counters, so I hope that fits your criteria.
You can use the fact that in PHP a string can be thought of as an array of characters.
Then basically what you want to do is to replace each character $i on the left side of the middle of the string with the character $j on the right side of the middle with the same distance.
For example, in a string of seven characters the middle character is on position 3. The character on position 0 (distance 3) needs to be swapped with the character on position 6 (3 + 3), the character on position 1 (distance 2) needs to be swapped with the character on position 5 (3 + 2), etc.
This algorithm can be implemented as follows:
$s = 'abcdefg';
$length = strlen($s);
for ($i = 0, $j = $length-1; $i < ($length / 2); $i++, $j--) {
$t = $s[$i];
$s[$i] = $s[$j];
$s[$j] = $t;
}
var_dump($s);
$string = 'abc';
$reverted = implode(array_reverse(str_split($string)));
You could use the XOR swap trick.
function rev($str) {
$len = strlen($str);
for($i = 0; $i < floor($len / 2); ++$i) {
$str[$i] = $str[$i] ^ $str[$len - $i - 1];
$str[$len - $i - 1] = $str[$i] ^ $str[$len - $i - 1];
$str[$i] = $str[$i] ^ $str[$len - $i - 1];
}
return $str;
}
print rev("example");
Try this:
$s = 'abcdefg';
for ($i = strlen($s)-1; $i>=0; $i--) {
$s .= $s[$i];
$s[$i] = NULL;
}
var_dump(trim($s));
Here it is PHP7 version of this:
echo "\u{202E}abcdefg"; // outs: gfedcba
PHP strings are kinda-sorta mutable, but due to copy-on-write it's very difficult to modify them in-place without a copy being made. Some of the above solutions work, but only because they're stand-alone; some already fail because they define a function without a pass-by-reference argument. To get the code to actually operate in-place in a larger program, you'd need to pay careful attention to assignments, function arguments, and scopes.
Example:
$string1 = 'abc';
$string2 = $string1;
$string1[0] = 'b';
print("$string1, $string2");
> "abc, bbc"
I suppose that if between initializing the variable and modifying it you only ever used by-reference assignments (&=) and reference arguments (function rev(&$string)) (or assign the string to an object property initially, and then never assign it to any other variable), you might be able to change the original value of the string without making any copies. That's a bit ridiculous, however, and I'd assume that the interviewer who came up with that question didn't know about copy-on-write.
This isn't quite the same as immutability in other languages, by the way, because it applies to arrays too:
$a = [0, 1, 2];
$b = $a;
$b[0] = 1;
print(implode($a).implode($b));
> "012112"
To sum up, all types (except for objects as of PHP5) are assigned with copy-on-write unless you specifically use the &= operator. The assignment doesn't copy them, but unlike most other languages (C, Java, Python...) that either change the original value (arrays) or don't allow write access at all (strings), PHP will silently create a copy before making any changes.
Of course, if you switched to a language with more conventional pointers and also switched to byte arrays instead of strings, you could use XOR to swap each pair of characters in place:
for i = 0 ... string.length / 2:
string[i] ^= string[string.length-1-i]
string[string.length-1-i] ^= string[i]
string[i] ^= string[string.length-1-i]
Basically #EricBouwers answer, but you can remove the 2nd placeholder variable $j
function strrev2($str)
{
$len = strlen($str);
for($i=0;$i<$len/2;$i++)
{
$tmp = $str[$i];
$str[$i] = $str[$len-$i-1];
$str[$len-$i-1] = $tmp;
}
return $str;
}
Test for the output:
echo strrev2("Hi there!"); // "!ereht iH"
echo PHP_EOL;
echo strrev2("Hello World!"); // "!dlroW olleH"
This will go through the list and stop halfway, it swaps the leftmost and rightmost, and works it's way inward, and stops at the middle. If odd numbered, the pivot digit is never swapped with itself, and if even, it swaps the middle two and stops. The only extra memory used is $len for convenience and $tmp for swapping.
If you want a function that doesn't return a new copy of the string, but just edits the old one in place you can use the following:
function strrev3(&$str)
{
$len = strlen($str);
for($i=0;$i<$len/2;$i++)
{
$tmp = $str[$i];
$str[$i] = $str[$len-$i-1];
$str[$len-$i-1] = $tmp;
}
}
$x = "Test String";
echo $x; // "Test String"
strrev3($x);
echo PHP_EOL;
echo $x; // "gnirtS tseT"
Using &$str passes a direct pointer the the string for editing in place.
And for a simpler implementation like #treegardens, you can rewrite as:
$s = 'abcdefghijklm';
$len = strlen($s);
for($i=0; $i < $len/2; $i++) {
list($s[$i], $s[$len-$i-1]) = array($s[$len-$i-1], $s[$i]);
}
echo $s;
It has the similar logic, but I simplified the for-loop quite a bit.
Its Too Simple
//Reverse a String
$string = 'Basant Kumar';
$length = strlen($string);
for($i=$length-1;$i >=0;$i--){
echo $string[$i];
}
Here is my code to solve your problem
<?php
$s = 'abcdefg';
for ($i = 0, $length = mb_strlen($s); $i < $length; $i++) {
$s = $s{$i}.mb_substr($s,0,$i).mb_substr($s,$i+1);
}
var_dump($s);
?>
You could also use a recursion to reverse the string. Something like this for example:
function reverse($s) {
if(strlen($s) === 1) return $s;
return substr($s, strlen($s)-1) . reverse(substr($s , 0, strlen($s)-1));
}
What you do here is actually returning the last character of the string and then calling again the same function with the substring that contains the initial string without the last character. When you reach the point when your string is just one character then you end the recursion.
You can use this code to reverse a string without using the reserved function in php.
Code:
<?php
function str_rev($y)// function for reversing a string by passing parameters
{
for ($x = strlen($y)-1; $x>=0; $x--) {
$y .= $y[$x];
$y[$x] = NULL;
}
echo $y;
}
str_rev("I am a student");
?>
Output:
tneduts a ma I
In the above code, we have passed the value of the string as the parameter.We have performed the string reversal using for loop.
you could use substr with negative start.
Theory & Explanation
you can start with for loop with counter from 1 to length of string, and call substr inside iteration with counter * -1 (which will convert the counter into negative value) and length of 1.
So for the first time counter would be 1 and by multiplying with -1 will turn it to -1
Hence substr('abcdefg', -1, 1); will get you g
and next iteration substr('abcdefg', -2, 1); will get you f
and substr('abcdefg', -3, 1); will get you e
and so on ...
Code
$str = 'abcdefghijklmnopqrstuvwxyz';
for($i=1; $i <= strlen($str); $i++) {
echo substr($str, $i*-1, 1);
}
In Action: https://eval.in/583208
public function checkString($str){
if(!empty($str)){
$i = 0;
$str_reverse = '';
while(isset($str[$i])){
$strArr[] = $str[$i];
$i++;
}
for($j = count($strArr); $j>= 0; $j--){
if(isset($strArr[$j])){
$str_reverse .= $strArr[$j];
}
}
if($str == $str_reverse){
echo 'It is a correct string';
}else{
echo 'Invalid string';
}
}
else{
echo 'string not found.';
}
}
//Reverse String word by word
$str = "Reverse string word by word";
$i = 0;
while ($d = $str[$i]) {
if($d == " ") {
$out = " ".$temp.$out;
$temp = "";
}
else
$temp .= $d;
$i++;
}
echo $temp.$out;
The following solution is very simple, but it does the job:
$string = 'Andreas';
$reversedString = '';
for($i = mb_strlen($string) - 1; $i >= 0; $i--){
$reversedString .= $string[$i];
}
var_dump($reversedString) then results: string(7) "saerdnA"
<?php
$value = 'abcdefg';
$length_value = strlen($value);
for($i = $length_value-1; $i >=0 ;$i--){
echo $value[$i];
}
?>
you can try this..
$string = "NASEEM";
$total_word = strlen($string);
for($i=0; $i<=$total_word; $i++)
{
echo substr($string,$total_word-$i,1);
}
i have used some built in function but without str_rev function .
<?php
$text = "red";
$arr = str_split($text);
$rev_text = array_reverse($arr);
echo join(" ",$rev_text);
?>
Try This
<?php
$str="abcde";
for($i=strlen($str)-1;$i>=0;$i--){
echo $str[$i];
}
?>
output
edcba
This is my solution to solve this.
$in = 'This is a test text';
$out = '';
// find string length
$len = strlen($in);
// loop through it and print it reverse
for ( $i = $len - 1; $i >=0;$i-- )
{
$out = $out.$in[$i];
}
echo $out;
Reverse string using recursion function.
$reverseString = '';
function Reverse($str, $len)
{
if ($len == 0) {
return $GLOBALS['reverseString'];
} else {
$len--;
$GLOBALS['reverseString'] .= $str[$len];
return Reverse($str, $len);
}
}
$str = 'Demo text';
$len = strlen($str);
echo Reverse($str, $len)
Try this
$warn = 'this is a test';
$i=0;
while(#$warn[$i]){
$i++;}
while($i>0)
{
echo $warn[$i-1]; $i--;
}

Truncating a string after x amount of charcters

I have a string that that is an unknown length and characters.
I'd like to be able to truncate the string after x amount of characters.
For example from:
$string = "Hello# m#y name # is Ala#n Colem#n"
$character = "#"
$x = 4
I'd like to return:
"Hello# m#y name # is Ala#"
Hope I'm not over complicating things here!
Many thanks
I'd suggest explode-ing the string on #, then getting the 1st 4 elements in that array.
$string = "Hello# m#y name # is Ala#n Colem#n";
$character = "#";
$x = 4;
$split = explode($character, $string);
$split = array_slice($split, 0, $x);
$newString = implode($character, $split).'#';
function posncut( $input, $delim, $x ) {
$p = 0;
for( $i = 0; $i < $x; ++ $i ) {
$p = strpos( $input, $delim, $p );
if( $p === false ) {
return "";
}
++ $p;
}
return substr( $input, 0, $p );
}
echo posncut( $string, $character, $x );
It finds each delimiter in turn (strpos) and stops after the one you're looking for. If it runs out of text first (strpos returns false), it gives an empty string.
Update: here's a benchmark I made which compares this method against explode: http://codepad.org/rxTt79PC. Seems that explode (when used with array_pop instead of array_slice) is faster.
Something along these lines:
$str_length = strlen($string)
$character = "#"
$target_count = 4
$count = 0;
for ($i = 0 ; $i<$str_length ; $i++){
if ($string[$i] == $character) {
$count++
if($count == $target_count) break;
}
}
$result = sub_str($string,0,$i)

Replace the string for each occurrence in php?

I would like to do some simple replacement using php.
For the first occurrence of "xampp" , replace it as "xp".
For the second / last occurrence of "xampp", replace it as "rrrr"
$test = "http://localhost/xampp/splash/xampp/.php";
echo $test."<br>";
$count = 0;
$test = str_replace ("xampp","xp",$test,$count);
echo $test."<br>";
$count = 1;
$test = str_replace ("xampp","rrrr",$test,$count);
echo $test;
After looking the doc, I found that $count is to return the place where the string matchs only. It do not replace the string by specific occurrence assigned. So are there any ways to do the task?
You could do it with preg_replace_callback, but strpos should be more efficient if the replacements aren't necessarily sequential.
function replaceOccurrence($subject, $find, $replace, $index) {
$index = 0;
for($i = 0; $i <= $index; $i++) {
$index = strpos($subject, $find, $index);
if($index === false) {
return $subject;
}
}
return substr($subject, 0, $index) . $replace . substr($subject, $index + strlen($find));
}
Here's a demo.

keyword highlight is highlighting the highlights in PHP preg_replace()

I have a small search engine doing its thing, and want to highlight the results. I thought I had it all worked out till a set of keywords I used today blew it out of the water.
The issue is that preg_replace() is looping through the replacements, and later replacements are replacing the text I inserted into previous ones. Confused? Here is my pseudo function:
public function highlightKeywords ($data, $keywords = array()) {
$find = array();
$replace = array();
$begin = "<span class=\"keywordHighlight\">";
$end = "</span>";
foreach ($keywords as $kw) {
$find[] = '/' . str_replace("/", "\/", $kw) . '/iu';
$replace[] = $begin . "\$0" . $end;
}
return preg_replace($find, $replace, $data);
}
OK, so it works when searching for "fred" and "dagg" but sadly, when searching for "class" and "lass" and "as" it strikes a real issue when highlighting "Joseph's Class Group"
Joseph's <span class="keywordHighlight">Cl</span><span <span c<span <span class="keywordHighlight">cl</span>ass="keywordHighlight">lass</span>="keywordHighlight">c<span <span class="keywordHighlight">cl</span>ass="keywordHighlight">lass</span></span>="keywordHighlight">ass</span> Group
How would I get the latter replacements to only work on the non-HTML components, but to also allow the tagging of the whole match? e.g. if I was searching for "cla" and "lass" I would want "class" to be highlighted in full as both the search terms are in it, even though they overlap, and the highlighting that was applied to the first match has "class" in it, but that shouldn't be highlighted.
Sigh.
I would rather use a PHP solution than a jQuery (or any client-side) one.
Note: I have tried to sort the keywords by length, doing the long ones first, but that means the cross-over searches do not highlight, meaning with "cla" and "lass" only part of the word "class" would highlight, and it still murdered the replacement tags :(
EDIT: I have messed about, starting with pencil & paper, and wild ramblings, and come up with some very unglamorous code to solve this issue. It's not great, so suggestions to trim/speed this up would still be greatly appreciated :)
public function highlightKeywords ($data, $keywords = array()) {
$find = array();
$replace = array();
$begin = "<span class=\"keywordHighlight\">";
$end = "</span>";
$hits = array();
foreach ($keywords as $kw) {
$offset = 0;
while (($pos = stripos($data, $kw, $offset)) !== false) {
$hits[] = array($pos, $pos + strlen($kw));
$offset = $pos + 1;
}
}
if ($hits) {
usort($hits, function($a, $b) {
if ($a[0] == $b[0]) {
return 0;
}
return ($a[0] < $b[0]) ? -1 : 1;
});
$thisthat = array(0 => $begin, 1 => $end);
for ($i = 0; $i < count($hits); $i++) {
foreach ($thisthat as $key => $val) {
$pos = $hits[$i][$key];
$data = substr($data, 0, $pos) . $val . substr($data, $pos);
for ($j = 0; $j < count($hits); $j++) {
if ($hits[$j][0] >= $pos) {
$hits[$j][0] += strlen($val);
}
if ($hits[$j][1] >= $pos) {
$hits[$j][1] += strlen($val);
}
}
}
}
}
return $data;
}
I've used the following to address this problem:
<?php
$protected_matches = array();
function protect(&$matches) {
global $protected_matches;
return "\0" . array_push($protected_matches, $matches[0]) . "\0";
}
function restore(&$matches) {
global $protected_matches;
return '<span class="keywordHighlight">' .
$protected_matches[$matches[1] - 1] . '</span>';
}
preg_replace_callback('/\x0(\d+)\x0/', 'restore',
preg_replace_callback($patterns, 'protect', $target_string));
The first preg_replace_callback pulls out all matches and replaces them with nul-byte-wrapped placeholders; the second pass replaces them with the span tags.
Edit: Forgot to mention that $patterns was sorted by string length, longest to shortest.
Edit; another solution
<?php
function highlightKeywords($data, $keywords = array(),
$prefix = '<span class="hilite">', $suffix = '</span>') {
$datacopy = strtolower($data);
$keywords = array_map('strtolower', $keywords);
$start = array();
$end = array();
foreach ($keywords as $keyword) {
$offset = 0;
$length = strlen($keyword);
while (($pos = strpos($datacopy, $keyword, $offset)) !== false) {
$start[] = $pos;
$end[] = $offset = $pos + $length;
}
}
if (!count($start)) return $data;
sort($start);
sort($end);
// Merge and sort start/end using negative values to identify endpoints
$zipper = array();
$i = 0;
$n = count($end);
while ($i < $n)
$zipper[] = count($start) && $start[0] <= $end[$i]
? array_shift($start)
: -$end[$i++];
// EXAMPLE:
// [ 9, 10, -14, -14, 81, 82, 86, -86, -86, -90, 99, -103 ]
// take 9, discard 10, take -14, take -14, create pair,
// take 81, discard 82, discard 86, take -86, take -86, take -90, create pair
// take 99, take -103, create pair
// result: [9,14], [81,90], [99,103]
// Generate non-overlapping start/end pairs
$a = array_shift($zipper);
$z = $x = null;
while ($x = array_shift($zipper)) {
if ($x < 0)
$z = $x;
else if ($z) {
$spans[] = array($a, -$z);
$a = $x;
$z = null;
}
}
$spans[] = array($a, -$z);
// Insert the prefix/suffix in the start/end locations
$n = count($spans);
while ($n--)
$data = substr($data, 0, $spans[$n][0])
. $prefix
. substr($data, $spans[$n][0], $spans[$n][1] - $spans[$n][0])
. $suffix
. substr($data, $spans[$n][1]);
return $data;
}
I had to revisit this subject myself today and wrote a better version of the above. I'll include it here. It's the same idea only easier to read and should perform better since it uses arrays instead of concatenation.
<?php
function highlight_range_sort($a, $b) {
$A = abs($a);
$B = abs($b);
if ($A == $B)
return $a < $b ? 1 : 0;
else
return $A < $B ? -1 : 1;
}
function highlightKeywords($data, $keywords = array(),
$prefix = '<span class="highlight">', $suffix = '</span>') {
$datacopy = strtolower($data);
$keywords = array_map('strtolower', $keywords);
// this will contain offset ranges to be highlighted
// positive offset indicates start
// negative offset indicates end
$ranges = array();
// find start/end offsets for each keyword
foreach ($keywords as $keyword) {
$offset = 0;
$length = strlen($keyword);
while (($pos = strpos($datacopy, $keyword, $offset)) !== false) {
$ranges[] = $pos;
$ranges[] = -($offset = $pos + $length);
}
}
if (!count($ranges))
return $data;
// sort offsets by abs(), positive
usort($ranges, 'highlight_range_sort');
// combine overlapping ranges by keeping lesser
// positive and negative numbers
$i = 0;
while ($i < count($ranges) - 1) {
if ($ranges[$i] < 0) {
if ($ranges[$i + 1] < 0)
array_splice($ranges, $i, 1);
else
$i++;
} else if ($ranges[$i + 1] < 0)
$i++;
else
array_splice($ranges, $i + 1, 1);
}
// create substrings
$ranges[] = strlen($data);
$substrings = array(substr($data, 0, $ranges[0]));
for ($i = 0, $n = count($ranges) - 1; $i < $n; $i += 2) {
// prefix + highlighted_text + suffix + regular_text
$substrings[] = $prefix;
$substrings[] = substr($data, $ranges[$i], -$ranges[$i + 1] - $ranges[$i]);
$substrings[] = $suffix;
$substrings[] = substr($data, -$ranges[$i + 1], $ranges[$i + 2] + $ranges[$i + 1]);
}
// join and return substrings
return implode('', $substrings);
}
// Example usage:
echo highlightKeywords("This is a test.\n", array("is"), '(', ')');
echo highlightKeywords("Classes are as hard as they say.\n", array("as", "class"), '(', ')');
// Output:
// Th(is) (is) a test.
// (Class)es are (as) hard (as) they say.
OP - something that's not clear in the question is whether $data can contain HTML from the get-go. Can you clarify this?
If $data can contain HTML itself, you are getting into the realms attempting to parse a non-regular language with a regular language parser, and that's not going to work out well.
In such a case, I would suggest loading the $data HTML into a PHP DOMDocument, getting hold of all of the textNodes and running one of the other perfectly good answers on the contents of each text block in turn.

cut particular pointed string using php

How I cut the extra 0 string from those sample.
current string: 0102000306
required string: 12036
Here a 0 value have in front of each number. So, i need to cut the extra all zero[0] value from the string and get my expected string. It’s cannot possible using str_replace. Because then all the zero will be replaced. So, how do I do it?
Using a regex:
$result = preg_replace('#0(.)#', '\\1', '0102000306');
Result:
"12036"
Using array_reduce:
$string = array_reduce(str_split('0102000306', 2), function($v, $w) { return $v.$w[1]; });
Or array_map+implode:
implode('',array_map('intval',str_split('0102000306',2)));
$currentString = '0102000306';
$length = strlen($currentString);
$newString = '';
for ($i = 0; $i < $length; $i++) {
if (($i % 2) == 1) {
$newString .= $currentString{$i};
}
}
or
$currentString = '0102000306';
$tempArray = str_split($currentString,2);
$newString = '';
foreach($tempArray as $val) {
$newString .= substr($val,-1);
}
It's not particularly elegant but this should do what you want:
$old = '0102000306';
$new = '';
for ($i = 0; $i < strlen($old); $i += 2) {
$new .= $old[$i+1];
}
echo $new;

Categories