Replace strings in php - php

I have a string that consists of tags <p> </p> and I want to replace them by <br />, but whenever I try using str_replace() it does not do so.
Is there any solution to it? Any other possible way to do it?
$string="<p> This is one para </p> <p> This is second </p>";
Using:
str_replace("</p> <p>","<br />",$string> nothing gets replaced.

Are you looking for something like this?
<?php
$string = "<p> This is one para </p> <p> This is second </p>";
$searchArray = array(
'<p>'
, '</p>'
);
$replaceArray = array(
''
, '<br />'
);
var_dump( str_replace($searchArray, $replaceArray, $string) );
?>
Output
string(47) " This is one para <br /> This is second <br />"

str_replace looks for an exact match, and replaces it. There is no "<p> </p>" in your string, and so it will never match. The behaviour you seem to be expecting is this:
If the string contains these substrings, replace them with this. Even if str_replace did behave that way, how would it know where to put the replacement?
I believe this is your intent;
$needles = array("<p>" => "",
"</p>" => "</br>");
$string = "<p> This is one para </p> <p> This is second </p>";
$match = true;
foreach($needles as $find => $replace)
{
if(strpos($string, $find) === false)
{
$match = false;
}
}
if($match)
{
foreach($needles as $find => $replace)
{
$string = str_replace($find, $replace, $string);
}
}
echo $string;
If the string matches all of the keys in $needles, it will replace them with the corresponding values in $needles. If you're going to be doing a lot more HTML manipulation however, then regular expressions using preg_replace would be a better approach.

Related

Check if a word occur in string and not to be in first and last

I am trying to check if word is occur in a string but not to be the first and last word, if its true then remove the space after and before of the word and replace with a underscore.
Input:
$str = 'This is a cool area";
Output:
$str = 'This is a_cool_area";
I want to check that the word 'cool' is inside the string but not a first and last word. if yes the remove the space & replace with '_'
You can use preg_replace to do this job, using this regex:
/(?<=\w)\s+(' . $word . ')\s+(?=\w)/i
which looks for the word, surrounded by at least one word character on either side (to prevent matching at the beginning or ending of the sentence). Usage in PHP:
$str = 'This is a cool area';
$word = 'cool';
$str = preg_replace('/(?<=\w)\s+(' . $word . ')\s+(?=\w)/i', '_$1_', $str);
echo $str . "\n";
$str = ' Cool areas are cool ';
$str = preg_replace('/(?<=\w)\s+(' . $word . ')\s+(?=\w)/i', '_$1_', $str);
echo $str . "\n";
Output:
This is a_cool_area
Cool areas are cool
Demo on 3v4l.org
function checkWord($str, $word)
{
$arr = explode(" ", $str);
$newArr = array_slice($arr, 1, -1);
$key = array_search($word, $newArr);
if($key !== false)
{
return implode('_',array_slice($arr, $key, 3));
}
else
{
return $str;
}
}
echo checkWord('This is a cool area', 'cool');

How to remove part of a string, that's wrapped in <b></b>, with php? [duplicate]

This question already has an answer here:
DOM php delete all tags by tag name
(1 answer)
Closed 7 years ago.
So I have a text being pulled from db:
<b>Object title</b>
<br />
<p>Object description</p>
and I need to remove <b>Object title</b>, I tried using substr, but didn't quite come up with the correct way of putting it together. Can you please show me how I could do that?
Edit
Please note: I need to remove only the first <b></b> element, every other bold part of that string should stay the way it is.
u shoud use preg_match for this problem.
$text = "<b>Object title</b><br /><p>Object description</p>";
if (!preg_match("/<b>.*<\/b>/",$text,$m)) {
str_replace($m[0],"",$text);
}
this should work for u.
if u want remove all u can run a a loop on $m.
This can be obtained without the use of regex as well.
We are using simple PHP string functions here:
Try this:
<?php
function removeTags($subject, $replaceStr){
$strlength = strlen($replaceStr);
$subject = strstr($subject, $replaceStr, true) . substr(strstr($subject, $replaceStr), 0 + $strlength);
return $subject;
}
$str = '<b>Object title</b><b>Object title</b><br /><p>Object description</p><b>Object title</b>';
$brOpenRemoved = removeTags($str, '<b>');
$brCloseRemoved = removeTags($brOpenRemoved, '</b>');
echo $brCloseRemoved; // final output
?>
The function removeTags removes the string provided to it. We have provided tags here.
It only removes first occurrence because we are using functions like strstr() which only work on first occurence of the string.
EDIT
We can use below function to prevent calling the same function again and again
<?php
function removeFirstOccurence($subject, $replaceTag){
$replaceStrings = ['<'.$replaceTag.'>', '</'.$replaceTag.'>'];
foreach($replaceStrings as $replaceStr){
$strlength = strlen($replaceStr);
$subject = strstr($subject, $replaceStr, true) . substr(strstr($subject, $replaceStr), 0 + $strlength);
}
return $subject;
}
$str = '<b>Object title</b><b>Object title</b><br /><p>Object description</p><b>Object title</b>';
$brRemoved = removeFirstOccurence($str, 'b');
echo $brRemoved; // final output
?>
If you are sure that there is your pattern in the text:
//remove first <b> tag
$text = '<b>foo</b>...';
$pos = strpos($text,'<b>');
if ($pos !== false) {
$newtext = substr_replace($text,'',$pos,strlen('<b>'));
}
//remove first </b> tag
$pos = strpos($text,'</b>');
if ($pos !== false) {
$newtext = substr_replace($newtext,'',$pos,strlen('</b>'));
}
You can use $limit to the maximum possible replacements for each pattern in preg_replace
$yourString =
"<b>Object title</b>
<br />
<p>Object description</p>";
$limit = 1;
$pattern = "/<b>(.*)<\/b>/";
$replace = "";
$newString = preg_replace($pattern, $replace, $yourString, $limit);
echo $newString;
output:
<br />
<p>Object description</p>
If you use (.*) you can also delete <b> and </b> tags and just stay with the content:
$limit = 1;
$pattern = "/<b>(.*)<\/b>/";
$replace = "$1";
$newString = preg_replace($pattern, $replace, $yourString, $limit);
echo $newString;
output:
Object title
<br />
<p>Object description</p>
Or keep only tags without content:
$limit = 1;
$pattern = "/<b>(.*)<\/b>/";
$replace = "<b></b>";
$newString = preg_replace($pattern, $replace, $yourString, $limit);
echo $newString;
output:
<b></b>
<br />
<p>Object description</p>

Preg Replace in PHP for Heading Tags

I have a markdown text content which I have to replace without using library functions.So I used preg replace for this.It works fine for some cases.For cases like heading
for eg Heading
=======
should be converted to <h1>Heading</h1> and also
##Sub heading should be converted to <h2>Sub heading</h2>
###Sub heading should be converted to <h3>Sub heading</h3>
I have tried
$text = preg_replace('/##(.+?)\n/s', '<h2>$1</h2>', $text);
The above code works but I need to have count of hash symbol and based on that I have to assign heading tags.
Anyone help me please....
Try using preg_replace_callback.
Something like this -
$regex = '/(#+)(.+?)\n/s';
$line = "##Sub heading\n ###sub-sub heading\n";
$line = preg_replace_callback(
$regex,
function($matches){
$h_num = strlen($matches[1]);
return "<h$h_num>".$matches[2]."</h$h_num>";
},
$line
);
echo $line;
The output would be something like this -
<h2>Sub heading</h2> <h3>sub-sub heading</h3>
EDIT
For the combined problem of using = for headings and # for sub-headings, the regex gets a bit more complicated, but the principle remains the same using preg_replace_callback.
Try this -
$regex = '/(?:(#+)(.+?)\n)|(?:(.+?)\n\s*=+\s*\n)/';
$line = "Heading\n=======\n##Sub heading\n ###sub-sub heading\n";
$line = preg_replace_callback(
$regex,
function($matches){
//var_dump($matches);
if($matches[1] == ""){
return "<h1>".$matches[3]."</h1>";
}else{
$h_num = strlen($matches[1]);
return "<h$h_num>".$matches[2]."</h$h_num>";
}
},
$line
);
echo $line;
Whose Output is -
<h1>Heading</h1><h2>Sub heading</h2> <h3>sub-sub heading</h3>
Do a preg_match_all like this:
$string = "#####asdsadsad";
preg_match_all("/^#/", $string, $matches);
var_dump ($matches);
And based on count of matches you can do whatever you want.
Or, use the preg_replace_callback function.
$input = "#This is my text";
$pattern = '/^(#+)(.+)/';
$mytext = preg_replace_callback($pattern, 'parseHashes', $input);
var_dump($mytext);
function parseHashes($input) {
var_dump($input);
$matches = array();
preg_match_all('/(#)/', $input[1], $matches);
var_dump($matches[0]);
var_dump(count($matches[0]));
$cnt = count($matches[0]);
if ($cnt <= 6 && $cnt > 0) {
return '<h' . $cnt . ' class="if you want class here">' . $input[2] . '</h' . $cnt . '>';
} else {
//This is not a valid h tag. Do whatever you want.
return false;
}
}

Remove the first paragraph tags from string

String
"<p>This is </p><p>Stackoverflow</p><p>site for programmers</p>"
Required Output
"This is <p>Stackoverflow</p><p>site for programmers</p>"
Small function
function remove_p($string)
{
$first_p=substr($string,0,3);
$p="<p>";
if($first_p==$p)
{
$string=str_replace('<p>','',$string,$temp=1);
$string=str_replace('</p>','',$string,$temp=1);
}
return $string;
}
But it removes all the <p> </p> tags.Why so?
I am basically writing this to remove the first paragraph tags created by ckeditor.
str_replace acts on all occurrences of a substring, not just the first. You will want to use a different function.
$string = preg_replace('~<p>(.*?)</p>~is', '$1', $string, /* limit */ 1);
To only remove the first <p> and </p> if at the start of the string, add a ^ after the first /.
See also: Using str_replace so that it only acts on the first match?
function replaceFirst($input, $search, $replacement){
$pos = stripos($input, $search);
if($pos === false){
return $input;
}
else{
$result = substr_replace($input, $replacement, $pos, strlen($search));
return $result;
}
}
$string = "This is <p>Stackoverflow</p><p>site for programmers</p>";
echo $string;
echo replaceFirst($string, '<p>', '');
Output:
This is <p>Stackoverflow</p><p>site for programmers</p>
This is Stackoverflow</p><p>site for programmers</p>
Source: #2031045
Hope this helps!
$str = "This is <p>Stackoverflow</p><p>site for programmers</p>";
function remove_p($string)
{
$string=str_replace('<p>','',$string,$temp=1);
$string=str_replace('<\p>','',$string,$temp=1);
return $string;
}
echo(remove_p($str));
The result is:
This is Stackoverflow
site for programmers
Try using the method of this answer.
function remove_p($string)
{
return replaceFirst(replaceFirst($string, '<p>', ''), '</p>', '');
}
Or read about Regular Expressions.

Inverse htmlentities / html_entity_decode

Basically I want to turn a string like this:
<code> <div> blabla </div> </code>
into this:
<code> <div> blabla </div> </code>
How can I do it?
The use case (bc some people were curious):
A page like this with a list of allowed HTML tags and examples. For example, <code> is a allowed tag, and this would be the sample:
<code><?php echo "Hello World!"; ?></code>
I wanted a reverse function because there are many such tags with samples that I store them all into a array which I iterate in one loop, instead of handling each one individually...
My version using regular expressions:
$string = '<code> <div> blabla </div> </code>';
$new_string = preg_replace(
'/(.*?)(<.*?>|$)/se',
'html_entity_decode("$1").htmlentities("$2")',
$string
);
It tries to match every tag and textnode and then apply htmlentities and html_entity_decode respectively.
There isn't an existing function, but have a look at this.
So far I've only tested it on your example, but this function should work on all htmlentities
function html_entity_invert($string) {
$matches = $store = array();
preg_match_all('/(&(#?\w){2,6};)/', $string, $matches, PREG_SET_ORDER);
foreach ($matches as $i => $match) {
$key = '__STORED_ENTITY_' . $i . '__';
$store[$key] = html_entity_decode($match[0]);
$string = str_replace($match[0], $key, $string);
}
return str_replace(array_keys($store), $store, htmlentities($string));
}
Update:
Thanks to #Mike for taking the time to test my function with other strings. I've updated my regex from /(\&(.+)\;)/ to /(\&([^\&\;]+)\;)/ which should take care of the issue he raised.
I've also added {2,6} to limit the length of each match to reduce the possibility of false positives.
Changed regex from /(\&([^\&\;]+){2,6}\;)/ to /(&([^&;]+){2,6};)/ to remove unnecessary excaping.
Whooa, brainwave! Changed the regex from /(&([^&;]+){2,6};)/ to /(&(#?\w){2,6};)/ to reduce probability of false positives even further!
Replacing alone will not be good enough for you. Whether it be regular expressions or simple string replacing, because if you replace the &lt &gt signs then the < and > signs or vice versa you will end up with one encoding/decoding (all &lt and &gt or all < and > signs).
So if you want to do this, you will have to parse out one set (I chose to replace with a place holder) do a replace then put them back in and do another replace.
$str = "<code> <div> blabla </div> </code>";
$search = array("<",">",);
//place holder for < and >
$replace = array("[","]");
//first replace to sub out < and > for [ and ] respectively
$str = str_replace($search, $replace, $str);
//second replace to get rid of original < and >
$search = array("<",">");
$replace = array("<",">",);
$str = str_replace($search, $replace, $str);
//third replace to turn [ and ] into < and >
$search = array("[","]");
$replace = array("<",">");
$str = str_replace($search, $replace, $str);
echo $str;
I think i have a small sollution, why not break html tags into an array and then compare and change if needed?
function invertHTML($str) {
$res = array();
for ($i=0, $j=0; $i < strlen($str); $i++) {
if ($str{$i} == "<") {
if (isset($res[$j]) && strlen($res[$j]) > 0){
$j++;
$res[$j] = '';
} else {
$res[$j] = '';
}
$pos = strpos($str, ">", $i);
$res[$j] .= substr($str, $i, $pos - $i+1);
$i += ($pos - $i);
$j++;
$res[$j] = '';
continue;
}
$res[$j] .= $str{$i};
}
$newString = '';
foreach($res as $html){
$change = html_entity_decode($html);
if($change != $html){
$newString .= $change;
} else {
$newString .= htmlentities($html);
}
}
return $newString;
}
Modified .... with no errors.
So, although other people on here have recommended regular expressions, which may be the absolute right way to go ... I wanted to post this, as it is sufficient for the question you asked.
Assuming that you are always using html'esque code:
$str = '<code> <div> blabla </div> </code>';
xml_parse_into_struct(xml_parser_create(), $str, $nodes);
$xmlArr = array();
foreach($nodes as $node) {
echo htmlentities('<' . $node['tag'] . '>') . html_entity_decode($node['value']) . htmlentities('</' . $node['tag'] . '>');
}
Gives me the following output:
<CODE> <div> blabla </div> </CODE>
Fairly certain that this wouldn't support going backwards again .. as other solutions posted, would, in the sense of:
$orig = '<code> <div> blabla </div> </code>';
$modified = '<CODE> <div> blabla </div> </CODE>';
$modifiedAgain = '<code> <div> blabla </div> </code>';
I'd recommend using a regular expression, e.g. preg_replace():
http://www.php.net/manual/en/function.preg-replace.php
http://www.webcheatsheet.com/php/regular_expressions.php
http://davebrooks.wordpress.com/2009/04/22/php-preg_replace-some-useful-regular-expressions/
Edit: It appears that I haven't fully answered your question. There is no built-in PHP function to do what you want, but you can do find and replace with regular expressions or even simple expressions: str_replace, preg_replace

Categories