How to replace the string and put new values using php regex - php

I have the following string
"Enter Contarct Fields wherever you want and enclose it with {}.You can use field's id or field's fieldcode for example {25} or {FIELD_CONTRACTTEXT}"
I want to replace this {25} and {FIELD_CONTRACTTEXT} with their equivalent value from databse.
Say 25 is a ID so I wanted to put name of the field of which 25 is the ID of.
There are many examples of replacing curly braces but no solution is there for replacing content like this. Please help me, I have tried many things.
PS: Please keep in mind that occurrence of {} is dynamic and 25 will not be a static number and there can be multiple {} in a string.

You can use preg_match_all() to find the occurrences, use this array to find the values in the database and then str_replace to replace each value after that.
To begin with you will need to fetch all the occurrences:
preg_match_all('/{(.*?)}/', $string, $matches, PREG_PATTERN_ORDER);
The matches array will look like this:
Array
(
[0] => Array
(
[0] => {}
[1] => {25}
[2] => {FIELD_CONTRACTTEXT}
)
[1] => Array
(
[0] =>
[1] => 25
[2] => FIELD_CONTRACTTEXT
)
)
You can then cylce through the array to find the individual elements that need to be replaced.
You can use the following to check the database and then replace values:
mysql_connect("localhost", "root", "");
mysql_select_db("data");
$string = "Enter Contarct Fields wherever you want and enclose it with {}.You can use field's id or field's fieldcode for example {25} or {FIELD_CONTRACTTEXT}";
preg_match_all('/{(.*?)}/', $string, $matches, PREG_PATTERN_ORDER);
foreach($matches[1] as $match) {
$sql = mysql_query("SELECT * FROM table WHERE `element`='".addslashes($match)."'");
if(mysql_num_rows($sql)==1){
$row = mysql_fetch_assoc($sql);
str_replace($string, "{".$match."}", $row['value']);
}
}
echo $string; //echos final output with replaced values

Related

Exploding string by comma outside parentheses

I have a string that I want to explode by commas but only if the comma is not nested inside some parentheses. This is a fairly common use case, and I have been reading through answered posts in this forum, but not really found what I am looking for.
So, in detail: the point is, i have a string (= SQL SELECT ... FROM statement), and I want to extract the elements from the list separated by comma encoded in this string (= the name of the columns that one wants to select from. However, these elements can contain brackets, and effectively be function calls. For example, in SQL one could do
SELECT TO_CHAR(min(shippings.shippingdate), 'YYYY-MM-DD') as shippingdate, nameoftheguy FROM shippings WHERE ...
Obviously, I would like to have an array now containing as first element
TO_CHAR(min(shippings.shippingdate), 'YYYY-MM-DD') as shippingdate
and as second element
nameoftheguy
The approaches I have followed so far are
PHP and RegEx: Split a string by commas that are not inside brackets (and also nested brackets),
PHP: Split a string by comma(,) but ignoring anything inside square brackets?,
Explode string except where surrounded by parentheses?, and
PHP: split string on comma, but NOT when between braces or quotes?
(focussing on the regex expressions therein, since I would like to do it with a single regex line), but in my little test area, those do not give the proper result. In fact, all of them split nothing or too much:
$Input: SELECT first, second, to_char(my,big,house) as bigly, export(mastermind and others) as aloah FROM
$Output: Array ( [0] => first [1] => second [2] => to_char [3] => (my,big,house) [4] => as [5] => bigly [6] => export [7] => (mastermind and others) [8] => as [9] => aloah )
The code of my test area is
<?php
function test($sql){
$foo = preg_match("/SELECT(.*?)FROM/", $sql, $match);
$bar = preg_match_all("/(?:[^(|]|\([^)]*\))+/", $match[1], $list);
//$bar = preg_match_all("/\((?:[^()]|(?R))+\)|'[^']*'|[^(),\s]+/", $match[1], $list);
//$bar = preg_match_all("/[,]+(?![^\[]*\])/", $match[1], $list);
//$bar = preg_match_all("/(?:[^(|]|\([^)]*\))+/", $match[1], $list);
//$bar = preg_match_all("/[^(,\s]+|\([^)]+\)/", $match[1], $list);
//$bar = preg_match_all("/([(].*?[)])|(\w)+/", $match[1], $list);
print "<br/>";
return $list[0];
}
print_r(test("SELECT first, second, to_char(my,big,house) as bigly, export(mastermind and others) as aloah FROM"));
?>
As you can imagine, I am not an regex expert, but I would like to do this splitting in a single line, if it is possible.
Following the conversation here, I did write a parser to solve this problem. It is quite ugly, but it does the job (at least within some limitations). For completeness (if anybody else might run into the same question), I post it here:
function full($sqlu){
$sqlu = strtoupper($sqlu);
if(strpos($sqlu, "SELECT ")===false || strpos($sqlu, " FROM ")===false) return NULL;
$def = substr($sqlu, strpos($sqlu, "SELECT ")+7, strrpos($sqlu, " FROM ")-7);
$raw = explode(",", $def);
$elements = array();
$rem = array();
foreach($raw as $elm){
array_push($rem, $elm);
$txt = implode(",", $rem);
if(substr_count($txt, "(") - substr_count($txt, ")") == 0){
array_push($elements, $txt);
$rem = array();
}
}
return $elements;
}
When feeding it with the following string
SELECT first, second, to_char(my,(big, and, fancy),house) as bigly, (SELECT myVar,foo from z) as super, export(mastermind and others) as aloah FROM table
it returns
Array ( [0] => first [1] => second [2] => to_char(my,(big, and, fancy),house) as bigly [3] => (SELECT myVar,foo from z) as super [4] => export(mastermind and others) as aloah )

Extract multiples strings from one variable by using preg_match

I'm having troubles extracting several strings between tags from a variable, in order to echo them inside a span individually.
Thing is, the tags in question are determined by a variable, here is what it looks like :
<?php
$string = "[en_UK]english1[/en_UK][en_UK]english2[/en_UK][fr_FR]francais1[/fr_FR][fr_FR]francais2[/fr_FR][fr_FR]francais3[/fr_FR]";
$lang = "en_UK";
preg_match("/(.[$lang]), (.[\/$lang])/", $string, $outputs_list);
foreach ($outputs_list as $output) {
echo "<span>".$output."/span>";
}
// in this exemple I want to output :
// <span>english1</span>
// <span>english2</span>
?>
It's my first time using preg_match and after trying so many differents things I'm kinda lost right now.
Basically I want to extract every strings contained between the tags [$lang] and [/$lang] (in my exemple $lang = "en_UK" but it will be determined by the user's cookies.
I'd like some help figuring this out if possible,
Thanks
[] in a regular expression makes a character class. I'm not sure what you're trying to do with the .s and , either. Your regex currently says:
Any single character, an e, n, _, U, or K, a , and space, and again any single character, an e, n, _, U, K, but this time also allowing /.
Regex demo: https://regex101.com/r/8pmy89/2
I also believe you were grouping the wrong value. The () go around what you want to capture, know as a capture group.
I think the regex you want is:
\[$lang\](.+?)\[\/$lang\]
Regex demo: https://regex101.com/r/8pmy89/3
PHP Usage:
$string = "[en_UK]english1[/en_UK][en_UK]english2[/en_UK][fr_FR]francais1[/fr_FR][fr_FR]francais2[/fr_FR][fr_FR]francais3[/fr_FR]";
$lang = "en_UK";
preg_match_all("/\[$lang\](.+?)\[\/$lang\]/", $string, $outputs_list);
foreach ($outputs_list[1] as $output) {
echo "<span>".$output."/span>";
}
PHP demo: https://eval.in/686086
Preg_match vs. preg_match_all
Preg_match only returns the first match(es) of a regex. Preg_match_all returns all matches of the regex. The 0 index has what the full regex matched. All subsequent indexes are each capture groups, e.g. 1 is the first capture group.
Simple Demo: https://eval.in/686116
$string = '12345';
preg_match('/(\d)/', $string, $match);
print_r($match);
preg_match_all('/(\d)/', $string, $match);
print_r($match);
Output:
Array
(
[0] => 1
[1] => 1
)
^ is preg_match, below is the preg_match_all
Array
(
[0] => Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 4
[4] => 5
)
[1] => Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 4
[4] => 5
)
)
I made little late to post this answer. #chris already answered your question, so i made the solution broad which might help other users who may have different requirements.
<?php
$string = "[en_UK]english1[/en_UK][en_UK]english2[/en_UK][fr_FR]francais1[/fr_FR][fr_FR]francais2[/fr_FR][fr_FR]francais3[/fr_FR]";
$lang = "en_UK";
echo "User Language -";
preg_match_all("/\[$lang\](.+?)\[\/$lang\]/", $string, $outputs_list);
foreach ($outputs_list[1] as $output) {
echo "<span>".$output.",</span>";
}
echo "<br/>All languages - ";
//if all lang
preg_match_all("/[a-zA-Z0-9]{3,}/", $string, $outputs_list);
foreach ($outputs_list[0] as $output) {
echo "<span>".$output.",</span>";
}
echo "<br/>Type of lang - ";
//for showing all type of lang
preg_match_all("/(\[[a-zA-Z_]+\])*/", $string, $outputs_list);
foreach ($outputs_list[1] as $output) {
echo "<span>".$output."</span>";
}
?>
OUTPUT
User Language -english1,english2,
All languages - english1,english2,francais1,francais2,francais3,
Type of lang - [en_UK][en_UK][fr_FR][fr_FR][fr_FR]

preg match to get text after # symbol and before next space using php

I need help to find out the strings from a text which starts with # and till the next immediate space by preg_match in php
Ex : I want to get #string from this line as separate.
In this example, I need to extract "#string" alone from this line.
Could any body help me to find out the solutions for this.
Thanks in advance!
PHP and Python are not the same in regard to searches. If you've already used a function like strip_tags on your capture, then something like this might work better than the Python example provided in one of the other answers since we can also use look-around assertions.
<?php
$string = <<<EOT
I want to get #string from this line as separate.
In this example, I need to extract "#string" alone from this line.
#maybe the username is at the front.
Or it could be at the end #whynot, right!
dog#cat.com would be an e-mail address and should not match.
EOT;
echo $string."<br>";
preg_match_all('~(?<=[\s])#[^\s.,!?]+~',$string,$matches);
print_r($matches);
?>
Output results
Array
(
[0] => Array
(
[0] => #string
[1] => #maybe
[2] => #whynot
)
)
Update
If you're pulling straight from the HTML stream itself, looking at the Twitter HTML it's formatted like this however:
<s>#</s><b>UserName</b>
So to match a username from the html stream you would match with the following:
<?php
$string = <<<EOT
<s>#</s><b>Nancy</b> what are you on about?
I want to get <s>#</s><b>string</b> from this line as separate. In this example, I need to extract "#string" alone from this line.
<s>#</s><b>maybe</b> the username is at the front.
Or it could be at the end <s>#</s><b>WhyNot</b>, right!
dog#cat.com would be an e-mail address and should not match.
EOT;
$matchpattern = '~(<s>(#)</s><b\>([^<]+)</b>)~';
preg_match_all($matchpattern,$string,$matches);
$users = array();
foreach ($matches[0] as $username){
$cleanUsername = strip_tags($username);
$users[]=$cleanUsername;
}
print_r($users);
Output
Array
(
[0] => #Nancy
[1] => #string
[2] => #maybe
[3] => #WhyNot
)
Just do simply:
preg_match('/#\S+/', $string, $matches);
The result is in $matches[0]

Preg_Match_All and RegEx Getting Values

I'm trying to get the 2 values in this string using regex:
a:2:{i:45;s:29:"Program Name 1";i:590;s:19:"Program Name 2";}
There are 2 variables that start with "s:" and end with ":" which I am attempting to get from this string (and similar strings.
$string = 'a:2:{i:45;s:29:"Program Name 1";i:590;s:19:"Program Name 2";}';
preg_match_all("/s:(\d+):/si", $page['perfarray'], $match);
print_r($match);
I have tried numerous things but this is the first time I've attempted to use regex to get multiple values from a string.
This is the current result: Array ( [0] => Array ( ) [1] => Array ( ) )
Any constructive help is greatly appreciated. I have already read the functions on php.net and I can't find a similar question on stack overflow that matches my needs closely enough. Thanks in advance.
That looks like a serialized string. Instead of using a regular expression, use unserialize() to retrieve the required value.
Update: It looks like your string is not a valid serialized string. In that case, you can use a regular expression to get the job done:
$string = 'a:2:{i:45;s:29:"Program Name 1";i:590;s:19:"Program Name 2";}';
if(preg_match_all("/s:(\d+):/si", $string, $matches)) {
print_r($matches[1]);
}
Output:
Array
(
[0] => 29
[1] => 19
)
That should work:
preg_match_all("/s:([0-9]+):/si", $page['perfarray'], $match);

regex assistance

I am trying to match a semi dynamically generated string. So I can see if its the correct format, then extract the information from it that I need. My Problem is I no matter how hard I try to grasp regex can't fathom it for the life of me. Even with the help of so called generators.
What I have is a couple different strings like the following. [#img:1234567890] and [#user:1234567890] and [#file:file_name-with.ext]. Strings like this pass through are intent on passing through a filter so they can be replaced with links, and or more readable names. But again try as I might I can't come up with a regex for any given one of them.
I am looking for the format: [#word:] of which I will strip the [, ], #, and word from the string so I can then turn around an query my DB accordingly for whatever it is and work with it accordingly. Just the regex bit is holding me back.
Not sure what you mean by generators. I always use online matchers to see that my test cases work. #Virendra almost had it except forgot to escape the [] charaters.
/\[#(\w+):(.*)\]/
You need to start and end with a regex delimeter, in this case the '/' character.
Then we escape the '[]' which is use by regex to match ranges of characters hence the '['.
Next we match a literal '#' symbol.
Now we want to save this next match so we can use it later so we surround it with ().
\w matches a word. Basically any characters that aren't spaces, punctuation, or line characters.
Again match a literal :.
Maybe useful to have the second part in a match group as well so (.*) will match any character any number of times, and save it for you.
Then we escape the closing ] as we did earlier.
Since it sounds like you want to use the matches later in a query we can use preg_match to save the matches to an array.
$pattern = '/\[#(\w+):(.*)\]/';
$subject = '[#user:1234567890]';
preg_match($pattern, $subject, $matches);
print_r($matches);
Would output
array(
[0] => '[#user:1234567890]', // Full match
[1] => 'user', // First match
[2] => '1234567890' // Second match
)
An especially helpful tool I've found is txt2re
Here's what I would do.
<pre>
<?php
$subj = 'An image:[#img:1234567890], a user:[#user:1234567890] and a file:[#file:file_name-with.ext]';
preg_match_all('~(?<match>\[#(?<type>[^:]+):(?<value>[^\]]+)\])~',$subj,$matches,PREG_SET_ORDER);
foreach ($matches as &$arr) unset($arr[0],$arr[1],$arr[2],$arr[3]);
print_r($matches);
?>
</pre>
This will output
Array
(
[0] => Array
(
[match] => [#img:1234567890]
[type] => img
[value] => 1234567890
)
[1] => Array
(
[match] => [#user:1234567890]
[type] => user
[value] => 1234567890
)
[2] => Array
(
[match] => [#file:file_name-with.ext]
[type] => file
[value] => file_name-with.ext
)
)
And here's a pseudo version of how I would use the preg_replace_callback() function:
function replace_shortcut($matches) {
global $users;
switch (strtolower($matches['type'])) {
case 'img' : return '<img src="images/img_'.$matches['value'].'jpg" />';
case 'file' : return ''.$matches['value'].'';
// add id of each user in array
case 'user' : $users[] = (int) $matches['value']; return '%s';
default : return $matches['match'];
}
}
$users = array();
$replaceArr = array();
$subj = 'An image:[#img:1234567890], a user:[#user:1234567890] and a file:[#file:file_name-with.ext]';
// escape percentage signs to avoid complications in the vsprintf function call later
$subj = strtr($subj,array('%'=>'%%'));
$subj = preg_replace_callback('~(?<match>\[#(?<type>[^:]+):(?<value>[^\]]+)\])~',replace_shortcut,$subj);
if (!empty($users)) {
// connect to DB and check users
$query = " SELECT `id`,`nick`,`date_deleted` IS NOT NULL AS 'deleted'
FROM `users` WHERE `id` IN ('".implode("','",$users)."')";
// query
// ...
// and catch results
while ($row = $con->fetch_array()) {
// position of this id in users array:
$idx = array_search($row['id'],$users);
$nick = htmlspecialchars($row['nick']);
$replaceArr[$idx] = $row['deleted'] ?
"<span class=\"user_deleted\">{$nick}</span>" :
"{$nick}";
// delete this key so that we can check id's not found later...
unset($users[$idx]);
}
// in here:
foreach ($users as $key => $value) {
$replaceArr[$key] = '<span class="user_unknown">User'.$value.'</span>';
}
// replace each user reference marked with %s in $subj
$subj = vsprintf($subj,$replaceArr);
} else {
// remove extra percentage signs we added for vsprintf function
$subj = preg_replace('~%{2}~','%',$subj);
}
unset($query,$row,$nick,$idx,$key,$value,$users,$replaceArr);
echo $subj;
You can try something like this:
/\[#(\w+):([^]]*)\]/
\[ escapes the [ character (otherwise interpreted as a character set); \w means any "word" character, and [^]]* means any non-] character (to avoid matching past the end of the tag, as .* might). The parens group the various matched parts so that you can use $1 and $2 in preg_replace to generate the replacement text:
echo preg_replace('/\[#(\w+):([^]]*)\]/', '$1 $2', '[#link:abcdef]');
prints link abcdef

Categories