Reputation: 5213
I'm working on an autocomplete for SSN-like numbers in PHP. So if the user searches for '123', it should find the number 444123555. I want to bold the results, thus, 444<b>123</b>555
. I then, however, want to format it as an SSN - thus creating 444-<b>12-3</b>555
.
Is there some way to say 'put the dash after the nth digit'? Because I don't want the nth character, just the nth digit - if I could say 'put a dash after the third digit and the fifth digit, ignoring non-numeric characters like <, b, and >' that would be awesome. Is this doable in a regex?
Or is there a different method that's escaping me here?
Upvotes: 2
Views: 477
Reputation: 1552
Here's a simple function using an iterative approach as Platinum Azure suggests:
function addNumberSeparator($numString, $n, $separator = '-')
{
$numStringLen = strlen($numString);
$numCount = 0;
for($i = 0; $i < $numStringLen; $i++)
{
if(is_numeric($numString[$i]))
{
$numCount++;
//echo $numCount . '-' . $i;
}
if($numCount == $n)
return substr($numString, 0, $i + 1) . $separator . substr($numString, $i + 1);
}
}
$string = '444<b>123</b>555';
$string = addNumberSeparator($string, 3);
$string = addNumberSeparator($string, 5);
echo $string;
This outputs the following:
4x<b>x123</b>555
That will, of course, only work with a non-numeric separator character. Not the most polished piece of code, but it should give you a start!
Hope that helps.
Upvotes: 1
Reputation:
If you want to get formated number and surrounding text:
<?php
preg_match("/(.*)(\d{3})(12)(3)(.*)/", "assd444123666as555", $match);
$str = $match[1];
if($match[2]!=="") $str.=$match[2]."-<b>";
$str.=$match[3]."-".$match[4]."</b>";
if($match[5]!=="") $str.=$match[5];
echo $str;
?>
If only formatted number:
<?php
preg_match("/(.*)(\d{3})(12)(3)(.*)/", "as444123666as555", $match);
$str = "";
if($match[2]!=="") $str.=$match[2]."-<b>";
$str.=$match[3]."-".$match[4]."</b>";
echo $str;
?>
Sorry, but it is a bit ambiguous.
Upvotes: 0
Reputation: 70763
This will do exactly what you asked for:
$str = preg_replace('/^ ((?:\D*\d){3}) ((?:\D*\d){2}) /x', '$1-$2-', $str);
The (?:\D*\d)
Will match any number of non-digits, then a digit. By repeating that n times, you match n digits, "ignoring" everything else.
Upvotes: 1
Reputation: 46193
Just iterate over the string and check that each character is a digit and count the digits as you go.
That will be so much faster than regex, even if regex were a feasible solution here (which I am not convinced it is).
Upvotes: 4