antesoles
antesoles

Reputation: 683

Formatting string according to pattern without regex in php

How can I format an arbitrary string according to a flexible pattern? The only solution I came up with is using regular expressions, but then I need 2 "patterns" (one for the search and one for the output).

Example:

$str = '123ABC5678"; 

Desired output: 12.3AB-C5-67.8

I would like to use a pattern in a variable (one that a user can easily define without knowledge of regular expressions) It could look like this:

$pattern = '%%.%%%-%%-%%.%';

So the user would just have to use 2 different characters (% and .)

A solution with regex would look like this:

$str = '123ABC5678';
$pattern_src = '@(.{2})(.{3})(.{2})(.{2})(.{1})@';
$pattern_rpl = "$1.$2-$3-$4.$5";

$res = preg_replace($pattern_src, $pattern_rpl, $str);
//$res eq 12.3AB-C5-67.8

Way too complicated since the user would need to define $pattern_src and $pattern_rpl. If the string could vary in length, it would be even more complex to explain.

Yes, I could write a function/parser that builds the required regular expressions based on a simple user pattern like %%.%%%-%%-%%.%. But I wonder if there is any "built in" way to achieve this with php? I was thinking about sprintf etc., but that doesn't seem to do the trick. Any ideas?

Upvotes: 1

Views: 1868

Answers (4)

mister martin
mister martin

Reputation: 6252

I was thinking about sprintf etc., but that doesn't seem to do the trick.

You're on the right track. You can accomplish this with vsprintf as follows:

$str = '123ABC5678';
$pattern = '%%.%%%-%%-%%.%';
echo vsprintf(str_replace('%', '%s', $pattern), str_split($str));

Output:

12.3AB-C5-67.8

This is assuming the number of % characters in $pattern match the length of $str.

Upvotes: 7

Andreas
Andreas

Reputation: 23958

How about this pattern from the user?

2.3-2-2.1
Where the pattern is a number means n chars, a dot or dash means add a dot or dash.

Now you make a regex to parse the user input:

preg_match_all("/(.)/", $User_input, $pattern);

Now you will have an array with either numbers or dots and dashes.

So loop through the array and build the string:

$string = '123ABC5678';
$User_input = "2.3-2-2.1";

preg_match_all("/(.)/", $User_input, $pattern);

$i=0;
$str="";
foreach($pattern[1] as $val){

    if(is_numeric($val)){
        $str .= substr($string,$i,$val);
        $i=$i+$val;
    }else{
        $str .= $val;
    }

}


 echo $str;

https://3v4l.org/5eg5G

Upvotes: 2

Blinkydamo
Blinkydamo

Reputation: 1584

I have a similar solution that looks like this.

<?php
$format = '%%.%%%-%%-%%.%';
$string = '123ABC5678';

$new_string = '';
$c = 0;
for( $i = 0; $i < strlen( $format ); $i++ )
{
  if( $format[ $i ] == '%' )
  {
    $new_string .= $string[ $c ];
    $c++;
  }
  else
  {
    $new_string .= $format[ $i ];
  }
}

echo $new_string;

Output:

12.3AB-C5-67.8

Upvotes: 2

Jirka Hrazdil
Jirka Hrazdil

Reputation: 4021

Why not write a simple parser that works as follows:

For each character of pattern:

  • if you match percent character, output next character from input
  • if you match any other character, output it

$str = '123ABC5678';
$pattern = '%%.%%%-%%-%%.%';

if (strlen($str) < substr_count($pattern, '%'))
  Die('The length of input string is lower than number number of placeholders');
$len = strlen($pattern);
$stringIndex = 0;
$output = '';
for ($i = 0; $i < $len; $i++) {
  if ($pattern[$i] === '%') {
    $output .= $str[$stringIndex];
    $stringIndex++;
  } else {
    $output .= $pattern[$i];
  }
}
echo $output;

Upvotes: 3

Related Questions