PHP comes with a huge variety of functions to work with strings. You can use these inbuilt PHP functions to trim strings, join them or to replace them. String functions in PHP are pretty powerful by themselves. You can use them to make case-insensitive changes or do multiple replacements at once. However, they still require you to specify exact strings that you want to replace.
Sometimes, that's not enough. You will come across a lot of situations where these replacements and matches have to be based on a pattern instead of some specific string. This is where regular expressions play a very important role.
In this tutorial you'll learn how to match, search and replace strings with regular expressions in PHP.
Let's begin with finding a match.
Using PHP preg_match()
to Search for Patterns in Strings in PHP
The PHP preg_match()
function is used to find a match within strings based on your specified pattern. It has two required parameters: the pattern and the string in which we want to find a match.
Keep in mind that this function only returns 1
, 0
, or false
depending on whether there was a match, no match or an error occurred. However, you can specify an array as the optional third parameter to fill it up with relevant information about the match.
<?php $pattern = '/[A-Z][a-z]+/'; $text = 'Adam, Andrew, or Monty will answer all your questions if you call us at 1234567890 on weekdays between 9:00AM to 5:00PM.'; $names = []; $is_match = preg_match($pattern, $text, $names); echo $is_match; // Output: 1 var_dump($names); /* array(1) { [0]=> string(4) "Adam" */ ?>
Names written in the English language usually begin with a capital letter and contain alphabets from a to z. We use this rule to come up with a very basic pattern and get matches for different names in a given text.
Using preg_match()
above returned 1
because it found a match. Remember that this function does not return the total number of matches or the position at which the match was found. It simply returns 1
if the match was found and 0
if no match was found.
The array $names
contains a single element which is supposed to be the fully matched string. Any subsequent elements will respective sub-pattern matches. Here is an example:
<?php $pattern = '/([A-Z])([a-z]+)/'; $text = 'Adam, Andrew or Monty will answer all your questions if you call us at 1234567890 on weekdays between 9:00AM to 5:00PM.'; $names = []; $is_match = preg_match($pattern, $text, $names); echo $is_match; // 1 var_dump($names); /* array(3) { [0]=> string(4) "Adam" [1]=> string(1) "A" [2]=> string(1) "dam" } */ ?>
The preg_match_all()
function works just like preg_match()
but returns the number of full pattern matches on success or false on failure. One thing you should remember is that the search for next matches continues from the end position of the previous match.
<?php $pattern = '/[A-Z][a-z]+/'; $text = 'Adam, Andrew or Monty will answer all your questions if you call us at 1234567890 on weekdays between 9:00AM to 5:00PM.'; $names = []; $match_count = preg_match_all($pattern, $text, $names); echo $match_count; // 3 var_dump($names); /* array(1) { [0]=> array(3) { [0]=> string(4) "Adam" [1]=> string(6) "Andrew" [2]=> string(5) "Monty" } } */ ?>
Observant readers might have noticed that preg_match_all()
returned a multi-dimensional array. This is because the first array contains a list of all the full matches and other arrays are supposed to contain a list of subsequent capture groups if they exist.
<?php $pattern = '/([A-Z])([a-z]+)/'; $text = 'Adam, Andrew or Monty will answer all your questions if you call us at 1234567890 on weekdays between 9:00AM to 5:00PM.'; $names = []; $match_count = preg_match_all($pattern, $text, $names); echo $match_count; // 3 var_dump($names); /* array(3) { [0]=> array(3) { [0]=> string(4) "Adam" [1]=> string(6) "Andrew" [2]=> string(5) "Monty" } [1]=> array(3) { [0]=> string(1) "A" [1]=> string(1) "A" [2]=> string(1) "M" } [2]=> array(3) { [0]=> string(1) "dam" [1]=> string(1) "ndrew" [2]=> string(1) "onty" } } */ ?>
As you might have observed, preg_match_all()
only returns the number of full pattern matches.
Using preg_replace()
to Search and Replace in PHP
You can use the preg_replace()
function to search for patterns in a string and then replace them. This function accepts three required parameters. The first one is the pattern you want to find. The second one is the replacement and the third parameter is the string in which you want to make these replacements. All of these parameters can either be a single value or an array.
Here are some examples of using preg_replace()
to help you understand how it works with different kinds of parameters.
<?php $pattern = '/\d{10}/'; $replacement = 'contact@test.com'; $text = 'Adam, Andrew or Monty will answer all your questions if you contact us at 1234567890 on weekdays between 9:00AM to 5:00PM.'; $new_text = preg_replace($pattern, $replacement, $text); var_dump($new_text); /* string(128) "Adam, Andrew or Monty will answer all your questions if you contact us at contact@test.com on weekdays between 9:00AM to 5:00PM." */ ?>
Here, the $pattern
and $replacement
were single single string values. Our intent was to replace the phone number with an email address where people can contact us. Using a regular expression ensures that we can replace all different 10 digit phone numbers at once.
<?php $patterns = ['/([A-Z][a-z]+, )+[A-Z][a-z]+/', '/\d{10}/']; $replacements = ['Amanda, Ashley, Susan', 'contact@test.com']; $text = 'Adam, Andrew, Shaun or Monty will answer all your questions if you contact us at 1234567890 on weekdays between 9:00AM to 5:00PM.'; $new_text = preg_replace($patterns, $replacements, $text); var_dump($new_text); /* string(137) "Amanda, Ashley, Susan or Monty will answer all your questions if you contact us at contact@test.com on weekdays between 9:00AM to 5:00PM." */ ?>
This time we supplied both the patterns and replacements as an array. You can see in the example that the parts matching the first pattern were replaced by the first replacement string in $replacements
.
There will be times when you would want the matched patterns to be part of the replaced string in PHP. This can be done easily with capture groups. Here is an example in which we add the set of new names to previous list instead of replacing it.
<?php $patterns = ['/(([A-Z][a-z]+, )+[A-Z][a-z]+)/', '/\d{10}/']; $replacements = ['${1}, Amanda, Ashley, Susan', 'contact@test.com']; $text = 'Adam, Andrew, Shaun or Monty will answer all your questions if you contact us at 1234567890 on weekdays between 9:00AM to 5:00PM.'; $new_text = preg_replace($patterns, $replacements, $text); var_dump($new_text); /* string(158) "Adam, Andrew, Shaun, Amanda, Ashley, Susan or Monty will answer all your questions if you contact us at contact@test.com on weekdays between 9:00AM to 5:00PM." */ ?>
We used parentheses around our first pattern to turn it into a single capture group. This becomes out first capture group and using ${1}
in the replacement string prepends the old list of names to new ones.
<?php $patterns = ['/(([A-Z][a-z]+, )+[A-Z][a-z]+)/', '/\d{10}/']; $replacements = ['Amanda, Ashley, Susan', 'contact@test.com']; $texts = ['Adam, Andrew, Shaun or Monty will answer all your questions if you contact us at 1234567890 on weekdays between 9:00AM to 5:00PM.', 'John, Monty and Jessica can also be contacted at 0123456789 on weekends.']; $new_text = preg_replace($patterns, $replacements, $texts); var_dump($new_text); /* array(2) { [0]=> string(137) "Amanda, Ashley, Susan or Monty will answer all your questions if you contact us at contact@test.com on weekdays between 9:00AM to 5:00PM." [1]=> string(88) "Amanda, Ashley, Susan and Jessica can also be contacted at contact@test.com on weekends." } */ ?>
In our last example, we provided preg_replace()
with multiple strings within which we wanted to perform replacements. As you can see, all the replacements are applied on each piece of text individually.
Using preg_replace_callback()
to Search and Replace Using Callback Functions in PHP
In the previous section, we saw how powerful regular expressions can be to replace strings which match a specific pattern. We can even use capture groups to reuse the match we found somewhere else in the replacement string.
Sometimes, we need even more control than that to modify the capture group as we see fit before doing any replacements. Using the preg_replace_callback()
function will be the perfect choice for that.
We have replaced all the different phone numbers with a single email address in all our examples so far. However, it is more probable that a company with different phone numbers will also have different dedicated email addresses. The preg_replace_callback()
function allows us to do these replacements on a case-by-case basis so that we can make appropriate changes to the replacement string based on the contents of the match.
<?php function update_email($matches) { $name_lower = strtolower($matches[1]); $email_address = $name_lower.'@test.com'; return $matches[1].' ('.$matches[2].' - '.$email_address.')'; } $pattern = '/([A-Z][a-z]+) \((\d{10})\)/'; $text = 'Adam (1234567890), Andrew (0567894321) or Monty (9876501234) will answer all your questions if you contact us on weekdays between 9:00AM to 5:00PM.'; $new_text = preg_replace_callback($pattern, "update_email", $text); var_dump($new_text); /* string(198) "Adam (1234567890 - adam@test.com), Andrew (0567894321 - andrew@test.com) or Monty (9876501234 - monty@test.com) will answer all your questions if you contact us on weekdays between 9:00AM to 5:00PM." */ ?>
In this example, every team member had a different phone number and we had to replace the phone number with a combination of phone number and email addresses. This can be done very easily with preg_replace_callback()
.
We begin by defining our own function update_email()
which takes in the $matches
as its input. The $matches
array is the same one we discussed when talking about preg_match()
. The first element in $matches
will be the whole match and other elements will contain the subsequent sub-patterns.
The regular expression in our pattern contains two capture groups to get the name and phone number as separate elements. We use the name of the person to get our email address by converting it to lowercase using strtolower()
and then appending @test.com
. Finally, we return our new replacement text.
The newer version of our main string now contains both the phone number and the email address of the employees.
Using preg_split()
to Split Strings in PHP
The preg_split()
function comes in handy when you want to split a main string into multiple substrings based on specific patterns. This is like explode()
on steroids.
This function accepts four parameters. The first two are required in every call of the function and they specify the pattern we should search for and the main string. The next two parameters are optional and they specify how many string should be returned and if the returned values should be modified with flags.
Here is an example that shows you how to get individual names from a string containing big list of names. The names are separated either by one or more spaces, one or more comma and one or more -
or _
characters.
<?php $pattern = '/[\s,\-_]/'; $text = 'Adam, Amanda Susan-Holly, Andrew---Monty--Shaun'; $all_names = preg_split($pattern, $text, -1, PREG_SPLIT_NO_EMPTY); var_dump($all_names); /* array(7) { [0]=> string(4) "Adam" [1]=> string(6) "Amanda" [2]=> string(5) "Susan" [3]=> string(5) "Holly" [4]=> string(6) "Andrew" [5]=> string(5) "Monty" [6]=> string(5) "Shaun" } */ ?>
We set the third parameter to -1
to get all the possible splits. The flag PREG_SPLIT_NO_EPMTY
is then used to get rid of any empty strings.
Final Thoughts
In this tutorial, we learned how to use some common and useful functions related to regular expressions in PHP. We began by learning how to use preg_match()
or preg_match_all()
to get all the strings that match a specific pattern. After that, we learned how to use preg_replace()
and preg_replace_callback()
to replace the matched patterns with some other string.
Regular expressions give us a very powerful and yet fragile tool to manipulate strings in PHP. You have to be careful when defining your patterns but they save a lot of time if used properly.
No comments:
Post a Comment