How to use preg_replace_callback? - php

I have the following HTML statement
[otsection]Wallpapers[/otsection]
WALLPAPERS GO HERE
[otsection]Videos[/otsection]
VIDEOS GO HERE
What I am trying to do is replace the [otsection] tags with an html div. The catch is I want to increment the id of the div from 1->2->3, etc..
So for example, the above statement should be translated to
<div class="otsection" id="1">Wallpapers</div>
WALLPAPERS GO HERE
<div class="otsection" id="2">Videos</div>
VIDEOS GO HERE
As far as I can research, the best way to do this is via a preg_replace_callback to increment the id variable between each replacement. But after 1 hour of working on this, I just cant get it working.
Any assistance with this would be much appreciated!

Use the following:
$out = preg_replace_callback(
"(\[otsection\](.*?)\[/otsection\])is",
function($m) {
static $id = 0;
$id++;
return "<div class=\"otsection\" id=\"ots".$id."\">".$m[1]."</div>";
},
$in);
In particular, note that I used a static variable. This variable persists across calls to the function, meaning that it will be incremented every time the function is called, which happens for each match.
Also, note that I prepended ots to the ID. Element IDs should not start with numbers.
For PHP before 5.3:
$out = preg_replace_callback(
"(\[otsection\](.*?)\[/otsection\])is",
create_function('$m','
static $id = 0;
$id++;
return "<div class=\"otsection\" id=\"ots".$id."\">".$m[1]."</div>";
'),
$in);

Note: The following is intended to be a general answer and does not attempt to solve the OP's specific problem as it has already been addressed before.
What is preg_replace_callback()?
This function is used to perform a regular expression search-and-replace. It is similar to str_replace(), but instead of plain strings, it searches for a user-defined regex pattern, and then applies the callback function on the matched items. The function returns the modified string if matches are found, unmodified string otherwise.
When should I use it?
preg_replace_callback() is very similar to preg_replace() - the only difference is that instead of specifying a replacement string for the second parameter, you specify a callback function.
Use preg_replace() when you want to do a simple regex search and replace. Use preg_replace_callback() when you want to do more than just replace. See the example below for understanding how it works.
How to use it?
Here's an example to illustrate the usage of the function. Here, we are trying to convert a date string from YYYY-MM-DD format to DD-MM-YYYY.
// our date string
$string = '2014-02-22';
// search pattern
$pattern = '~(\d{4})-(\d{2})-(\d{2})~';
// the function call
$result = preg_replace_callback($pattern, 'callback', $string);
// the callback function
function callback ($matches) {
print_r($matches);
return $matches[3].'-'.$matches[2].'-'.$matches[1];
}
echo $result;
Here, our regular expression pattern searches for a date string of the format NNNN-NN-NN where N could be a digit ranging from 0 - 9 (\d is a shorthand representation for the character class [0-9]). The callback function will be called and passed an array of matched elements in the given string.
The final result will be:
22-02-2014
Note: The above example is for illustration purposes only. You should not use to parse dates. Use DateTime::createFromFormat() and DateTime::format() instead. This question has more details.

Related

How can I camelcase a string in php

Is there a simple way I can have php camelcase a string for me? I am using the Laravel framework and I want to use some shorthand in a search feature.
It would look something like the following...
private function search(Array $for, Model $in){
$results = [];
foreach($for as $column => $value){
$results[] = $in->{$this->camelCase($column)}($value)->get();
}
return $results;
}
Called like
$this->search(['where-created_at' => '2015-25-12'], new Ticket);
So the resulting call in the search function I would be using is
$in->whereCreateAt('2015-25-12')->get();
The only thing is I can't figure out is the camel casing...
Have you considered using Laravel's built-in camel case functtion?
$camel = camel_case('foo_bar');
Full details can be found here:
https://laravel.com/docs/4.2/helpers#strings
So one possible solution that could be used is the following.
private function camelCase($string, $dontStrip = []){
/*
* This will take any dash or underscore turn it into a space, run ucwords against
* it so it capitalizes the first letter in all words separated by a space then it
* turns and deletes all spaces.
*/
return lcfirst(str_replace(' ', '', ucwords(preg_replace('/[^a-z0-9'.implode('',$dontStrip).']+/', ' ',$string))));
}
It's a single line of code wrapped by a function with a lot going on...
The breakdown
What is the dontStrip variable?
Simply put it is an array that should contain anything you don't want removed from the camelCasing.
What are you doing with that variable?
We are taking every element in the array and putting them into a single string.
Think of it as something like this:
function implode($glue, $array) {
// This is a native PHP function, I just wanted to demonstrate how it might work.
$string = '';
foreach($array as $element){
$string .= $glue . $element;
}
return $string;
}
This way you're essentially gluing all your elements in your array together.
What's preg_replace, and what's it doing?
preg_replace is a function that uses a regular expression (also known as regex) to search for and then replace any values that it finds, which match the desired regex...
Explanation of the regex search
The regex used in the search above implodes your array $dontStrip onto a little bit a-z0-9 which just means any letter A to Z as well as numbers 0 to 9. The little ^ bit tells regex that it's looking for anything that isn't whatever comes after it. So in this case it's looking for any and all things that aren't in your array or a letter or number.
If you're new to regex and you want to mess around with it, regex101 is a great place to do it.
ucwords?
This can be most easily though of as upper case words. It will take any word (a word being any bit of characters separated by a space) and it will capitalize the first letter.
echo ucwords('hello, world!');
Will print `Hello, World!'
Okay I understand what preg_replace is, what str_replace?
str_replace is the smaller, less powerful but still very useful little brother/sister to preg_replace. By this I mean that it has a similar use. str_replace doesn't regex, but does use a literal string so whatever you type into the first parameter is exactly what it will look for.
Side note, it is worth mentioning for anyone considering only using preg_replace where str_replace would work just as well. str_replace has been noted to be benchmarked a bit faster than preg_replace on larger apps.
lcfirst What?
Since about PHP 5.3 we have been able to use the lcfirst function, which much like ucwords, it's just a text manipulation function. `lcfirst turns the first letter into it's lower case form.
echo lcfirst('HELLO, WORLD!');
Will print 'hELLO, WORLD!'
Results
All this in mind the camelCase function uses distinct non-alphanumeric characters as break points to turn a string to a camelCase string.
There's a general purpose open source library that contains a method that performs case convertions for several popular case formats. library is called TurboCommons, and the formatCase() method inside the StringUtils does camel case conversion.
https://github.com/edertone/TurboCommons
To use it, import the phar file to your project and:
use org\turbocommons\src\main\php\utils\StringUtils;
echo StringUtils::formatCase('sNake_Case', StringUtils::FORMAT_CAMEL_CASE);
// will output 'sNakeCase'
You can use Laravel's built-in camel case helper function
use Illuminate\Support\Str;
$converted = Str::camel('foo_bar');
// fooBar
Full details can be found here:
https://laravel.com/docs/9.x/helpers#method-camel-case
Use the in-built Laravel Helper Function - camel_case()
$camelCase = camel_case('your_text_here');

PHP regular expression: Match exact word without other characters

I have a string that is like this ?supercategory=1&category=14&page=2 and I have a function that removes a selected filter from within that string and then returns it.
My regular expression is preg_replace('/(category=[0-9]+)&?/', '', $queryString)
Obviously the above code matches supercategory, but I want to match category in the string, not supercategory
How do I make this possible ?
I want to mention that the position of category and supercategory in the string can be changed.
Thanks
Rather than trying to use a regexp, this is a lot simpler using PHP's built-in parse_str(), unset() the category element, then use http_build_query() to recreate the query string
$dataString = 'supercategory=1&category=14&page=2';
parse_str($dataString, $urlArguments);
if (isset($urlArguments['category'])) {
unset($urlArguments['category']);
}
$dataString = http_build_query($urlArguments);
var_dump($dataString);

preg_match_all with callback?

I'm interested in replace numeric matches in real time and manipulate them to hexadecimal.
I was wonder if it's possible without using foreach loop.
so iow...
every thing in between :
= {numeric value} ;
will be manupulated to :
= {hexadecimal numeric value} ;
preg_match_all('/\=[0-9]\;/',$src,$matches);
Is there any callback to preg_match_all so instead of preform a loop afterwards I can manipulate them as soon as preg_match_all catch every match (real time).
this is not correct syntax but just so you can get the idea :
preg_match_all_callback('/\=[0-9]\;/',$src,$matches,{convertAll[0-9]ToHexadecimal});
You want preg_replace_callback().
You would match them with a regex like /=\d+?;/ and then your callback would look like...
function($matches) { return dechex($matches[1]); }
Combined, it gives us...
preg_replace_callback('/=(\d+?);/', function($matches) {
return dechex($matches[1]);
}, $str);
CodePad.
Alternatively, you could use positive lookbehind/forward to match the delimiters and then pass 'dechex' straight as the callback.
Or you could use T-Regx tool, which is far better! (automatic delimiters, exceptions instead of warnings, cleaner API)
pattern('=(\d+?);')->replace($str)->group(1)->callback('dechex');
or if you prefer the anonymous function
pattern('=(\d+?);')->replace($str)->group(1)->callback(function (Group $group) {
return dechex($group);
});

PHP - Replace various case types in string with hyperlink and retain original case

I have the following string:
"This is my string with three instances of MYTEXT. That was the first instance. This is the second instance of Mytext. And this is the third instance of mytext."
I need to replace each instance of Mytext (all three instances) with a version wrapped in a tag, so I want to wrap HTML tags around each instance. This is easy enough and I have no problem doing this. My question is - how do I do this while retaining the original case of each instance. The output I need is:
"This is my string with three instances of MYTEXT. That was the first instance. This is the second instance of Mytext. And this is the third instance of mytext."
I've been looking at str_ireplace and preg_teplace but none of them seem to do the job.
Any ideas?
Thanks in advance.
You can use backreferences to accomplish this:
preg_replace('/mytext/i', '\\0', $str);
The \\0 backreference in the replacement string will be replaced with the entire match, effectively maintaining the original case.
An alternative, and far more inefficient solution that uses the basics.
<?php
$string = "This is my string with three instances of MYTEXT. That was the first instance. This is the second instance of Mytext. And this is the third instance of mytext.";
$copyOfString = $string; // A copy of the original string, so that you can use the original string later.
$matches = array(); // An array to fill with the matches returned by the PHP function using Regular Expressions.
preg_match_all("/mytext/i", $string, $matches); // The above-mentioned function. Note that the 'i' makes the search case-insensitive.
foreach($matches as $matchSubArray){
foreach($matchSubArray as $match){ // This is only one way to do this.
$replacingString = "<b>".$match."</b>"; // Edit to use the tags you want to use.
$copyOfString = str_replace($match, $replacingString, $copyOfString); // str_replace is case-sensitive.
}
}
echo $copyOfString; // Output the final, and modified string.
?>
NOTE: As I hinted at in the beginning, this approach uses bad programming practice.

Error trying to pass regex match to function

I'm getting Syntax error, unexpected T_LNUMBER, expecting T_VARIABLE or '$'
This is the code i'm using
function wpse44503_filter_content( $content ) {
$regex = '#src=("|\')'.
'(/images/(19|20)(0-9){2}/(0|1)(0-9)/[^.]+\.(jpg|png|gif|bmp|jpeg))'.
'("|\')#';
$replace = 'src="'.get_site_url( $2 ).'"';
$output = preg_replace( $regex, $replace, $content );
return $output;
}
This is the line where i'm getting that error $replace = 'src="'.get_site_url( $2 ).'"';
Can anyone help me to fix it?
Thanks
You can't have '$2' as a variable name. It must start with a letter or underscore.
http://php.net/manual/en/language.variables.basics.php
Variable names follow the same rules as other labels in PHP. A valid variable name starts with a letter or underscore, followed by any number of letters, numbers, or underscores. As a regular expression, it would be expressed thus: '[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*'
Edit Above was my original answer and is the correct answer to the simple "syntax error" question. More in-depth answer below...
You are trying to use $2 to represent "the second capture group", but you haven't done anything at that point to match your regex. Even if $2 was a valid PHP variable name, it still wouldn't be set at that point in your script. Because of this, you can determine that you are using preg_replace improperly and that it may not suit your actual needs.
Note that the preg_replace documentation doesn't support using $n as a separate variable outside of the replacement operation. In other words, 'foo' . $1 . 'bar' is not a valid replacement string, but 'foo$1bar' is.
Depending on the complexity of get_site_url, you have 2 options:
If get_site_url is simply adding a root directory or server name, you could change your replacement string to src="/myotherlocation$2". This will effectively replace "/image/..." with "/myotherlocation/image/..." in the img src. This will not work if get_site_url is doing something more complex.
If get_site_url is complex, you should use preg_replace_callback per other answers. Give the documentation a read and post a new question (or I guess update this question?) if you have trouble with the implementation.
What you're trying to do (ie replacing the matched string with the result of a function call) can't be done using preg_replace, you'll need to use preg_replace_callback instead to get a function called for every match.
A short example of preg_replace_callback;
$get_site_url = // Returns replacement
function($row) {
return '!'.$row[1].'!'; // row[1] is first "backref"
};
$str = 'olle';
$regex = '/(ll)/'; // String to match
$output = preg_replace_callback( // Match, calling get_site_url for replacement
$regex,
$get_site_url,
$str);
var_dump($output); // output "o!ll!e"
PHP variable names cant begin with a number.
$2 is not a valid PHP variable. If you meant the second group in the regex then you want to put \2 in a string. However, since you're passing it to a function then you'll need to use preg_replace_callback() instead and substitute appropriately in the callback.
if PHP variable begins with number use following:
when I was getting the following as the result set from thrid party API
Code Works
$stockInfo->original->data[0]->close_yesterday
Code Failed
$stockInfo->original->data[0]->52_week_low
Solution
$stockInfo->original->data[0]->{'52_week_high'}

Categories