I know a bit about Regular Expression but really want to learn more about it and now i'm trying to make a function that detects all {} in my content (from a database) and checks what between the brackets. If there is a POST or GET with a name (format: POST:name or GET:name} i would like to replace them with that value.
Example:
When i have a form with the following inputs:
Name
Email
Message
And then in the value attribute i type: {POST:Name}
Then the script must detect the {POST:Name} and will replace it with the string in $_POST['name']. I already searched on Google, but found too much that i don't know what to really use.
Now i have:
<?php
preg_match_all("/{(POST|GET):[.*](})/", $content, $matches, PREG_SET_ORDER);
foreach($matches AS $match)
{
if(isset($_POST[$match]))
$content = str_replace('{POST:'.$match, $_POST[$match], $content);
else
$content = str_replace('{GET:'.$match, $_GET[$match], $content);
}
?>
But this don't work.
You should use preg_replace, better than str_replace.
And if you use preg_replace, you don't need no more your first condition, et can do the same code with only one instruction.
http://fr2.php.net/preg_replace
<?php preg_replace('#{(POST|GET):(.*)}#','$_$1[$2]',$content); ?>
My regex can be false, but something like this should work.
Related
I have latex + html code somewhere in the following form:
...some text1.... \[latex-code1\]....some text2....\[latex-code2\]....etc
Firstly I want to obtain the latex codes in an array codes[] to be able to send them to a server for rendering, so that
code[0]=latex-code1, code[1]=latex-code2, etc
Secondly, I want to modify this text so that it looks like:
...some text1.... <img src="root/1.png">....some text2....<img src="root/2.png">....etc
i.e, the i-th latex code fragment is replaced by the link to the i-th rendered image.
I have been trying to do this with preg_replace_callback and preg_match_all but being new to PHP haven't been able to make it work. Please advise.
If you're looking for codez:
$html = '...some text1.... \[latex-code1\]....some text2....\[latex-code2\]....etc';
$codes = array();
$count = 0;
$replace = function($matches) use (&$codes, &$count) {
list(, $codes[]) = $matches;
return sprintf('<img src="root/%d.png">', ++$count);
};
$changed = preg_replace_callback('~\\\\\\[(.+?)\\\\\\]~', $replace, $html);
echo "Original: $html\n";
echo "Changed : $changed\n\nLatex Codes: ", print_r($codes, 1), "Count: ", $count;
I don't know at which part you've got the problems, if it's the regex pattern, you use characters inside your markers that needs heavy escaping: For PHP and PCRE, that's why there are so many slashes.
Another tricky part is the callback function because it needs to collect the codes as well as having a counter. It's done in the example with an anonymous function that has variable aliases / references in it's use clause. This makes the variables $codes and $count available inside the callback.
I would like to know if it's possible to execute the php code in a string. I mean if I have:
$string = If i say <?php echo 'lala';?> I wanna get "<?php echo 'dada'; ?>";
Does anybody knows how?
[EDIT] It looks like nobody understood. I wanna save a string like
$string = If i say <?php count(array('lala'));?>
in a database and then render it. I can do it using
function render_php($string){
ob_start();
eval('?>' . $string);
$string = ob_get_contents();
ob_end_clean();
return $string;
}
The problem is that I does not reconize php code into "" (quotes) like
I say "<?php echo 'dada'; ?>"
$string = ($test === TRUE) ? 'lala' : 'falala';
There are lots of ways to do what it looks like you're trying to do (if I'm reading what you wrote correctly). The above is a ternary. If the condition evaluates to true then $string will be set to 'lala' else set to 'falala'.
If you're literally asking what you wrote, then use the eval() function. It takes a passed string and executes it as if it were php code. Don't include the <?php ?> tags.
function dropAllTables() {
// drop all tables in db
}
$string = 'dropAllTables();';
eval($string); // will execute the dropAllTables() function
[edit]
You can use the following regular expression to find all the php code:
preg_match_all('/(<\?php )(.+?)( \?>)/', $string, $php_code, PREG_OFFSET_CAPTURE);
$php_code will be an array where $php_code[0] will return an array of all the matches with the code + <?php ?> tags. $php_code[2] will be an array with just the code to execute.
So,
$string = "array has <?php count(array('lala')); ?> 1 member <?php count(array('falala')); ?>";
preg_match_all('/(<\?php )(.+?)( \?>)/', $string, $php_code, PREG_OFFSET_CAPTURE);
echo $php_code[0][0][0]; // <?php count(array('lala')); ?>
echo $php_code[2][0][0]; // count(array('lala'));
This should be helpful for what you want to do.
Looks like you are trying to concatenate. Use the concatenation operator "."
$string = "if i say " . $lala . " I wanna get " . $dada;
or
$string = "if i say {$lala} I wanna get {$dada}.";
That is what I get since your string looks to be a php variable.
EDIT:
<?php ?> is used when you want to tell the PHP interpreter that the code in those brackets should be interpreted as PHP. When working within those PHP brackets you do not need to include them again. So as you would just do this:
// You create a string:
$myString = "This is my string.";
// You decide you want to add something to it.
$myString .= getMyNameFunction(); // not $myString .= <?php getMyNameFunction() ?>;
The string is created, then the results of getMyNameFunction() are appended to it. Now if you declared the $myString variable at the top of your page, and wanted to use it later you would do this:
<span id="myString"><?php echo $myString; ?></span>
This would tell the interpreter to add the contents of the $myString variable between the tags.
Use token_get_all() on the string, then look for a T_OPEN_TAG token, start copying from there, look for a T_CLOSE_TAG token and stop there. The string between the token next to T_OPEN_TAG and until the token right before T_CLOSE_TAG is your PHP code.
This is fast and cannot fail, since it uses PHP's tokenizer to parse the string. You will always find the bits of PHP code inside the string, even if the string contains comments or other strings which might contain ?> or any other related substrings that will confuse regular expressions or a hand-written, slow, pure PHP parser.
I would consider not storing your PHP code blocks in a database and evaluating them using eval. There is usually a better solution. Read about Design Pattern, OOP, Polymorphism.
You could use the eval() function.
I'm working on a simple templating system. Basically I'm setting it up such that a user would enter text populated with special tags of the form: <== variableName ==>
When the system would display the text it would search for all tags of the form mentioned and replace the variableName with its corresponding value from a database result.
I think this would require a regular expression but I'm really messed up in REGEX here. I'm using php btw.
Thanks for the help guys.
A rather quick and dirty hack here:
<?php
$teststring = "Hello <== tag ==>";
$values = array();
$values['tag'] = "world";
function replaceTag($name)
{
global $values;
return $values[$name];
}
echo preg_replace('/<== ([a-z]*) ==>/e','replaceTag(\'$1\')',$teststring);
Output:
Hello world
Simply place your 'variables' in the variable array and they will be replaced.
The e modifier to the regular expression tells it to eval the replacement, the [a-z] lets you name the "variables" using the characters a-z (you could use [a-z0-9] if you wanted to include numbers). Other than that its pretty much standard PHP.
Very useful - Pointed me to what I was looking for...
Replacing tags in a template e.g.
<<page_title>>, <<meta_description>>
with corresponding request variables e,g,
$_REQUEST['page_title'], $_REQUEST['meta_description'],
using a modified version of the code posted:
$html_output=preg_replace('/<<(\w+)>>/e', '$_REQUEST[\'$1\']', $template);
Easy to change this to replace template tags with values from a DB etc...
If you are doing a simple replace, then you don't need to use a regexp. You can just use str_replace() which is quicker.
(I'm assuming your '<== ' and ' ==>' are delimiting your template var and are replaced with your value?)
$subject = str_replace('<== '.$varName.' ==>', $varValue, $subject);
And to cycle through all your template vars...
$tplVars = array();
$tplVars['ONE'] = 'This is One';
$tplVars['TWO'] = 'This is Two';
// etc.
// $subject is your original document
foreach ($tplVars as $varName => $varValue) {
$subject = str_replace('<== '.$varName.' ==>', $varValue, $subject);
}
Ahoy there!
I can't "guess" witch syntax should I use to be able to extract the source of an image but simply the web address not the src= neither the quotes?
Here is my piece of code:
function get_all_images_src() {
$content = get_the_content();
preg_match_all('|src="(.*?)"|i', $content, $matches, PREG_SET_ORDER);
foreach($matches as $path) {
echo $path[0];
}
}
When I use it I got this printed:
src="http://project.bechade.fr/wp-content/uploads/2009/09/mer-300x225.jpg"
And I wish to get only this:
http://project.bechade.fr/wp-content/uploads/2009/09/mer-300x225.jpg
Any idea?
Thanks for your help.
Not exactly an answer to your question, but when parsing html, consider using a proper html parser:
foreach($html->find('img') as $element) {
echo $element->src . '<br />';
}
See: http://simplehtmldom.sourceforge.net/
$path[1] instead of $path[0]
echo $path[1];
$path[0] is the full string matched. $path[1] is the first grouping.
You could explode the string using " as a delimeter and then the second item in the array you get would be the right string:
$array = explode('"',$full_src);
$bit_you_want = $array[1];
Reworking your original function, it would be:
function get_all_images_src() {
$content = get_the_content();
preg_match_all('|src="(.*?)"|i', $content, $matches, PREG_SET_ORDER);
foreach($matches as $path) {
$src = explode('"', $path);
echo $src[1];
}
}
Thanks Ithcy for his right answer.
I guess I've been too long to respond because he deleted it, I just don't know where his answer's gone...
So here is the one I've received by mail:
'|src="(.*?)"|i' makes no sense as a
regex. try '|src="([^"]+)"|i' instead.
(Which still isn't the most robust
solution but is better than what
you've got.)
Also, what everyone else said. You
want $path1, NOT $path[0]. You're
already extracting all the src
attributes into $matches[]. That has
nothing to do with $path[0]. If you're
not getting all of the src attributes
in the text, there is a problem
somewhere else in your code.
One more thing - you should use a real
HTML parser for this, because img tags
are not the only tags with src
attributes. If you're using this code
on raw HTML source, it's going to
match not just but
tags, etc.
— ithcy
I did everything he told me to do including using a HTML parser from Bart (2nd answer).
It works like a charm ! Thank you mate...
Okay so i set up this thing so that I can print out page that people came from, and then put dummy tags on certain pages. Some pages have commented out "linkto" tags with text in between them.
My problem is that some of my pages don't have "linkto" text. When I link to this page from there I want it to grab everything between "title" and "/title". How can I change the eregi so that if it turns up empty, it should then grab the title?
Here is what I have so far, I know I just need some kind of if/then but I'm a rank beginner. Thank you in advance for any help:
<?php
$filesource = $_SERVER['HTTP_REFERER'];
$a = fopen($filesource,"r"); //fopen("html_file.html","r");
$string = fread($a,1024);
?>
<?php
if (eregi("<linkto>(.*)</linkto>", $string, $out)) {
$outdata = $out[1];
}
//echo $outdata;
$outdatapart = explode( " " , $outdata);
echo $part[0];
?>
Here you go: if eregi() fails to match, the $outdata assignment will never happen as the if block will not be executed. If it matches, but there's nothing between the tags, $outdata will be assigned an empty string. In both cases, !$outdata will be true, so we can fallback to a second match on the title tag instead.
if(eregi("<linkto>(.*?)</linkto>", $string, $link_match)) {
$outdata = $link_match[1];
}
if(!$outdata && eregi("<title>(.*?)</title>", $string, $title_match)) {
$outdata = $title_match[1];
}
I also changed the (.*) in the match to (.*?). This means, don't be greedy. In the (.*) form, if you had $string set to
<title>Page Title</title> ...
... <iframe><title>A second title tag!</title></iframe>
The regex would match
Page Title</title> ... ... <iframe><title>A second title tag!
Because it tries to match as much as possible, as long as the text is between any and any other !. In the (.*?) form, the match does what you'd expect - it matches
Page Title
And stops as soon as it is able.
...
As an aside, this thing is an interesting scheme, but why do you need it? Pages can link to other pages and pass parameters via the query string:
...
Then somescript.php can access the prevpage parameter via the $_GET['prevpage'] superglobal variable.
Would that solve your problem?
The POSIX regex extension (ereg etc.) will be deprecated as of PHP 5.3.0 and may be gone completely come PHP 6, you're better off using the PCRE functions (preg_match and friends).
The PCRE functions are also faster, binary safe and support more features like non-greedy matching etc.
Just a pointer.
you need if, else.
if(eregi(...))
{
.
.
.
}
else
{
just grab title;
}
perhaps you should have done a quick google search to find this very simple answer.
Just add another if test before you assign the match to $outdata:
if (eregi("<linkto>(.*)</linkto>", $string, $out)) {
if ($out[1] != "") {
$outdata = $out[1];
} else {
// Look in the title.
}
}