Andrew
Andrew

Reputation: 5213

Put something after the nth digit, rather than nth character?

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

Answers (4)

Chris Hepner
Chris Hepner

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

user882255
user882255

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

Chronial
Chronial

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

Platinum Azure
Platinum Azure

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

Related Questions