根据 php 中没有正则表达式的模式格式化字符串

Formatting string according to pattern without regex in php

如何根据灵活的模式格式化任意字符串?我想到的唯一解决方案是使用正则表达式,但我需要 2 "patterns"(一个用于搜索,一个用于输出)。

示例:

$str = '123ABC5678"; 

期望输出:12.3AB-C5-67.8

我想在变量中使用一个模式(用户可以在不了解正则表达式的情况下轻松定义的模式)它可能看起来像这样:

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

因此用户只需使用 2 个不同的字符(% 和 .)

使用正则表达式的解决方案如下所示:

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

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

太复杂了,因为用户需要定义 $pattern_src 和 $pattern_rpl。如果字符串的长度可以变化,解释起来会更复杂。

是的,我可以编写一个 function/parser 来构建基于简单用户模式(如 %%.%%%-%%-%%.%)所需的正则表达式。但我想知道是否有任何 "built in" 方法可以用 php 实现这一点?我在考虑 sprintf 等,但这似乎并不能解决问题。有什么想法吗?

为什么不编写一个简单的解析器,其工作方式如下:

对于模式的每个字符:

  • 如果你匹配百分号字符,输出输入的下一个字符
  • 如果匹配到任何其他字符,则输出它

$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;

我有一个类似的解决方案,看起来像这样。

<?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;

输出:

12.3AB-C5-67.8

用户的这个模式怎么样?

2.3-2-2.1
其中模式是数字表示n个字符,点或破折号表示加点或破折号。

现在你制作一个正则表达式来解析用户输入:

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

现在您将拥有一个包含数字或点和破折号的数组。

因此遍历数组并构建字符串:

$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

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

你走在正确的轨道上。您可以使用 vsprintf 完成此操作,如下所示:

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

输出:

12.3AB-C5-67.8

这是假设 $pattern 中的 % 个字符的数量与 $str 的长度匹配。