Reputation: 1701
So I'm trying to split a string that contains a phone number and extension, as sometimes an extension exists in the string. This is my attempt:
$tests[] = "941-751-6550 ext 2204";
$tests[] = "(941) 751-6550 ext 2204";
$tests[] = "(941)751-6550 ext 2204";
$tests[] = "9417516550 ext 2204";
$tests[] = "941-751-6550 e 2204";
$tests[] = "941-751-6550 ext 2204 ";
$tests[] = "941-751-6550 extension 2204";
$tests[] = "941-751-6550 x2204";
$tests[] = "(941) 751-6550";
$tests[] = "(941)7516550";
$tests[] = "941-751-6550 ";
$tests[] = "941-751-6550";
foreach ($tests as $test) {
preg_match('#([\(\)\s0-9\-]+)(.+$)#',$test,$matches);
$phone = preg_replace('#[\-\(\)\s]#','',$matches[1]);
$extension = preg_replace('#[^0-9]#','',$matches[2]);
if ($phone == '9417516550'
&& ($extension == '2204'
|| $extension == '0')) {
echo "PASS: phone: $phone ext: $extension<br />";
} else {
echo "FAIL: phone: $phone ext: $extension<br />";
}
}
However, when I run these tests to see if it properly splits the phone number and the extension, I get the following output:
PASS: phone: 9417516550 ext: 2204
PASS: phone: 9417516550 ext: 2204
PASS: phone: 9417516550 ext: 2204
PASS: phone: 9417516550 ext: 2204
PASS: phone: 9417516550 ext: 2204
PASS: phone: 9417516550 ext: 2204
PASS: phone: 9417516550 ext: 2204
PASS: phone: 9417516550 ext: 2204
FAIL: phone: 941751655 ext: 0
FAIL: phone: 941751655 ext: 0
FAIL: phone: 9417516550 ext:
FAIL: phone: 941751655 ext: 0
As you can see, it breaks when I exclude an extension altogether (the last four tests). How might I correct the preg_match()
regex so that the FAIL: ...
lines look like PASS: phone: 9417516550 ext: 0
?
Upvotes: 1
Views: 235
Reputation: 405
Honestly, you're better off stripping the non-numeric characters, then splitting off anything after the first 10 as the extension. It's conceptually equivalent, but more straightforward and foolproof, and more efficient than running through multiple regexes, which are inherently slow.
foreach($tests as $test){
$phone = preg_replace("/[^0-9]/", "", $test);
$extension = substr($phone,10);
$phone = substr($phone,0,10);
if(empty($extension)){
$extension = '0';
}
if ($phone == '9417516550'
&& ($extension == '2204'
|| $extension == '0')) {
echo "PASS: phone: $phone ext: $extension<br />\n";
} else {
echo "FAIL: phone: $phone ext: $extension<br />\n";
}
}
Output:
PASS: phone: 9417516550 ext: 2204
PASS: phone: 9417516550 ext: 2204
PASS: phone: 9417516550 ext: 2204
PASS: phone: 9417516550 ext: 2204
PASS: phone: 9417516550 ext: 2204
PASS: phone: 9417516550 ext: 2204
PASS: phone: 9417516550 ext: 2204
PASS: phone: 9417516550 ext: 2204
PASS: phone: 9417516550 ext: 0
PASS: phone: 9417516550 ext: 0
PASS: phone: 9417516550 ext: 0
PASS: phone: 9417516550 ext: 0
Upvotes: 0
Reputation: 98961
$pns = <<< LOL
941-751-6550 ext 2204
(941) 751-6550 ext 2204
(941)751-6550 ext 2204
9417516550 ext 2204
941-751-6550 e 2204
941-751-6550 ext 2204
941-751-6550 extension 2204
941-751-6550 x2204
(941) 751-6550
(941)7516550
941-751-6550
941-751-6550
LOL;
preg_match_all('/^([(\d )\-]+)\s?(?:e.*?|x.*?)?(\d+)?$/sim', $pns, $matches, PREG_PATTERN_ORDER);
for ($i = 0; $i < count($matches[1]); $i++) {
$phone = preg_replace('#[\-\(\)\s]#','', $matches[1][$i]);
$extension = preg_replace('#[^0-9]#','', $matches[2][$i]);
if ($phone == '9417516550' && $extension == '2204') {
echo "PASS: phone: $phone ext: $extension\n";
} else {
echo "FAIL: phone: $phone ext: 0\n";
}
}
Output:
PASS: phone: 9417516550 ext: 2204
PASS: phone: 9417516550 ext: 2204
PASS: phone: 9417516550 ext: 2204
PASS: phone: 9417516550 ext: 2204
PASS: phone: 9417516550 ext: 2204
PASS: phone: 9417516550 ext: 2204
PASS: phone: 9417516550 ext: 2204
PASS: phone: 9417516550 ext: 2204
FAIL: phone: 9417516550 ext: 0
FAIL: phone: 9417516550 ext: 0
FAIL: phone: 9417516550 ext: 0
FAIL: phone: 9417516550 ext: 0
Upvotes: 0
Reputation: 333
This works as expected, just tested.
foreach ($tests as $test) {
preg_match('#([\(\)0-9\-]+\s*[\(\)0-9\-]+)\s*(.*$)#',$test,$matches);
$phone = preg_replace('#[\-\(\)\s]#','',$matches[1]);
$extension = ($matches[2] == "") ? '0' : preg_replace('#[^0-9]#','',$matches[2]);
if ($phone == '9417516550'
&& ($extension == '2204'
|| $extension == '0')) {
echo "PASS: phone: $phone ext: $extension<br />\n";
} else {
echo "FAIL: phone: $phone ext: $extension<br />\n";
}
}
With minimal changes on your code.
Upvotes: 1
Reputation: 23880
I'd do it all in the preg_match
. Assuming the numbers are non-international I think this would work.
foreach ($tests as $test) {
preg_match('#\(?(\d{3})\)?[-\h]?(\d{3})[-\h]?(\d{4})\h*(?:e?x?t?(?:ension)?\h(\d+))?#',$test,$matches);
$phone = $matches[1] . $matches[2] . $matches[3];
$extension = !empty($matches[4]) ? $matches[4] : 0;
if ($phone == '9417516550'
&& ($extension == '2204' || $extension == '0')) {
echo "PASS: phone: $phone ext: $extension<br />";
} else {
echo "FAIL: phone: $phone ext: $extension<br />";
}
}
Demo: https://eval.in/561720
Regex101 Demo: https://regex101.com/r/mG9iD1/1
Upvotes: 1
Reputation: 54831
(.+$)
means that in the end of a line must be 1 or more symbol. So, if you have nothing after phone number - then your phone number is reduced by 1 symbol.
I advise to use (.*$)
which means zero or more symbols.
Upvotes: 2
Reputation: 3002
From you example it looks like it fails when nothing found as ext.
A solution is to cast to int $extension
like this:
$extension = intval($extension); //If nothing found will be 0
After this we are sure that we have an integer
and we can change the if statement to:
|| $extension === 0)) {
Upvotes: 0