Using functions inside preg_replace - php

$TOPIC_CONTENT = preg_replace("!<code>(.+)</code>!is","<div style='color: #00FF00;
background-color: #000000; border-radius: 5px; margin: 5px;"<pre>".htmlspecialchars("$0")."</pre></div>",$TOPIC_INFO->content);
How can I get this to work? I have no idea how to pull this off, and I know my current way is invalid.

Use preg_replace_callback. Be a little careful with your regex .. I think you want to use .+? instead of just .+. The usual mantra is "don't parse html with regex," but for something as simple as this I don't see the harm.

Except for preg_replace_callback as in tandu's answer, you can also use the /e switch, and your replacement string will be *e*valuated as PHP code, and its result will be used.
I.e you could do:
preg_replace("!<code>(.+?)</code>!ise",
'"<pre style=\"color: #0f0; background: #000;\">" . htmlspecialchars("$1") . "</pre>"',
$string);

Related

Preg_match_all not giving the same results as preg_match

I have been trying to get all file resources inside an HTML.
My current version of the regex is
"[^']*'([^"]*)'[^']*" | "([^"]*)"
An example HTML (only a part):
<div style="background-image: url('/courses/UMASGRUPOBDEMO/document/learning_path/El_Contrato_de_Seguro-_Contenido_Teorico/video_pres_cto_seguro.jpg');display: block; margin-left: auto; margin-right: auto;"></div>
<img class="maximize"
src="/courses/CURSODESTINOPEQUENO/document/learning_path/LECCION_1_2_3_4_5_-_corta/Diapositiva01-29332.jpg" style="display: block; margin-left: auto; margin-right: auto;" />
Iterating preg_match I can get:
/courses/UMASGRUPOBDEMO/document/learning_path/El_Contrato_de_Seguro-_Contenido_Teorico/video_pres_cto_seguro.jpg
maximize
/courses/CURSODESTINOPEQUENO/document/learning_path/LECCION_1_2_3_4_5_-_corta/Diapositiva01-29332.jpg
But preg_match_all only give me the next one:
/courses/UMASGRUPOBDEMO/document/learning_path/El_Contrato_de_Seguro-_Contenido_Teorico/video_pres_cto_seguro.jpg
You can live test it at http://www.phpliveregex.com/p/h6T
Does this have any sense? Probably my regex needs something to work.
I have not much experience with regex. Please help me :)
Thanks you in advance!
Added:
The regex actually is something like:
any string delimited by double quotes which contains any string without double quotes and also contains two quotes inside with an optional content in between them
OR two double quotes with optional content inside (without double quotes)
As I am seeing, maybe the no quotes and no double quotes conditions should be touched a little to have better regex...
Now using a longer HTML example: http://www.phpliveregex.com/p/h74
<p><img class="maximize" src="/courses/UMASGRUPOBDEMO/document/learning_path/Diapositiva54/Diapositiva2.jpg" style="display: block; margin-left: auto; margin-right: auto;" alt="" /></p>
<div style="background-image: url('/courses/UMASGRUPOBDEMO/document/learning_path/El_Contrato_de_Seguro-_Contenido_Teorico/video_pres_cto_seguro.jpg');display: block; margin-left: auto; margin-right: auto;"></div>
<img class="maximize"
src="/courses/CURSODESTINOPEQUENO/document/learning_path/LECCION_1_2_3_4_5_-_corta/Diapositiva01-29332.jpg" style="display: block; margin-left: auto; margin-right: auto;" />
Try this regex instead:
"[^"']*'([^"']*)'[^"']*"|"([^"]*)"
Your original regex was greedily picking up everything from after the second ' to the last " in the input.
Remember that the * and + operators in regex are greedy meaning they will consume as much as possible in order to match.
You either must limit what those operators are applied to (as I did above) or turn them into non-greedy operators for the regex systems that support it, by using *? or +?:
"[^']*?'[^"]*?'[^']*?"
(However, this last one will still have issues, for example with <img src="foo" alt='bar' class="myimage" /> - which will grab 'bar' even though it's not part of a "-delimited string)

php code or regex to replace position of characters in a string

(Edit1: following George Cummins comment)I want you to help me create a regex search and replace or a php function to replace position of characters in a string. (since i couldn't figure it out on my own)
Say I have the following CSS :
padding: 1px 2px 3px 4px;
And I want to make it:
padding: 1px 4px 3px 2px;
That is - to replace left and right padding.
Regardless to the actual numbers, and throughout my entire css style sheet
Can anyone help ?
Edit2: Solved By Jonathan Kuhn - Thank you ! also added an imgur pic of what it looks like in sublime text
Something like:
preg_replace('/padding: (\d+px) (\d+px) (\d+px) (\d+px);/', 'padding: $1 $4 $3 $2;', $css);

preg_replace UNLESS string exists

I'm trying to add CSS styling to all hyperlinks unless it has a "donttouch" attribute.
E.g.
Style this: style me
Don't style this: <a href="http://whatever.com" donttouch>don't style me</a>
Here's my preg_replace without the "donttouch" exclusion, which works fine.
preg_replace('/<a(.*?)href="([^"]*)"(.*?)>(.*?)<\/a>/','<a$1href="$2"$3><span style="color:%link_color%; text-decoration:underline;">$4</span></a>', $this->html)
I've looked all over the place, and would appreciate any help.
Find (works also in Notepad++)
(?s)(<a (?:(?!donttouch)[^>])+>)(.*?)</a>
Replace with (Replace all in Notepad++):
\1<span style="whatever">\2</span></a>
This can be accomplished without a regular expression. Instead, use a CSS attribute selector.
For example, use these rules:
a { font-weight: bold; color: green }
a[donttouch=''] { font-weight: normal; color: blue }
Technically, you are styling the elements with the 'donttouch' attribute, but you can use default values. This will be more efficient than attempting to use a regular expression to parse your HTML, which is usually a bad idea.

Remove whitespace/new lines/comments. Regex?

I'm currently making sort of a CSS minifier and well, I think examples for what I'm trying to achieve are the simplest way to explain.
I'm trying to transform this:
/* CSS Content */
.class{
text-align:center;
border-bottom:1px solid #ccc;
}
.anotherclass, .another, .another{
text-align:center;
border-bottom:1px solid #ccc;
}
Into:
.class{text-align:center;border-bottom:1px solid #ccc;}.anotherclass,.another,.another{text-align:center;border-bottom:1px solid #ccc;}
Thus: removing comments, unnecessary whitespace and new lines.
So far I got to remove the comments and new lines (Using one expression and a function exploding the string on \n, then appending the parts). The whitespaces are a bit more difficult, since the whitespaces within the {} should be removed but not between the colon and semicolon.
Since I'm quite inexperienced with the use of regular expressions, have no good reference book at hand and Google does'nt seem to have the answer: I'm wondering if anyone here can help me with creating one good Regex to accomplish this.
Thanks in advance!
If you must do it this way then this will minify the example you gave:
(/\*[^/]+\*/|^\t*|^\s*|\n|\s+(?=[\{.])|(?<=[\{;])\s+)
It assumes the flavour of regex you're using allows positive look-behinds
I guess you could try something like this:
(?<=[{};])\s+|\/\*.+?\*\/
http://rubular.com/r/djDtEPzEV0
Cleans out whitespace in front of parentheses, semicolons and all comments.

preg_replace capture group check

I'm trying to add a new bbcode to my phpfusion application. Im using with preg_replace. Here's the code:
$text = preg_replace(
"#\[gameimg( float:(left|center|right))?\]((http|ftp|https|ftps)://)(.*?)(\.(jpg|jpeg|gif|png|JPG|JPEG|GIF|PNG))\[/gameimg\]#sie",
"'<span style=\"display: block; max-width: 350px; margin: 0 0 5px 5px; $1\"><img src=\"'
. (strlen('$3') > 0 ? '$3' : BASEDIR.GAMESDIR)
. '$5$6\" alt=\"$5$6\" style=\"border:0px; max-width: 350px;\" /></span>'",
$text
);
If I supply an absolute url (for ex. [gameimg]http://localhost/dirname/file.jpg[/gameimg]) everything works fine, the picture shows up as expected. But if i omit the protokol and hostname using relative url ([gameimg]dirname/file.jpg[/gameimg]) i expect to append the basedir.gamedir constant to the given url but it doesn't work at all, it prints out the original bbcode without any replacement, not the image. What am i doing wrong?
A couple things here:
That is a giant preg_replace call. Maybe you could break this problem into smaller parts so that it is easier to understand/maintain?
You are using the "ignore case" modifier (i), yet you have things like (jpg|JPG). This is redundant.
Your question asks why [gameimg] tags without http://.. don't get matched. Well this is because of the required ((http|ftp|https|ftps)://) in your regex. You should make this section optional by adding a ?, like this:
((http|ftp|https|ftps)://)?

Categories