繁体   English   中英

在 PHP 中搜索和替换给定模式中的字符串

[英]Search and replace a string within a given pattern in PHP

我正在尝试从给定的字符串模式生成 html,类似于插件。 共有三种模式,arg、arg 和arg 字符串模式。 我无法更改此模式,因为它来自 CMS。

{pluginName} or {pluginName=3} or {pluginName id=3|view=simple|arg999=asv}

一个例子:

<p>Hi this is a html page</p> 
<p>The following line should generate html</p>
{pluginName=3}
<p>The following line also should generate html</p>
{pluginName id=3|view=simple|arg999=asv}

我的目标是用一些东西替换那些“标签”(这与这个问题的处理无关)。 但是,我希望能够将给出的 args 传递给应该处理该逻辑的类/函数。

这是我的第一次尝试,没有使用正则表达式,因为我不知道如何用它们解决这个问题(主要是因为它们速度较慢)。

<?php
function processPlugins($text, $pos = 0, $start = '{', $end = '}') {
    $plugins = array('plugin1', 'plugin2');
    while(($pos = strpos($text, $start, $pos)) !== false) {
        $startPos = $pos;
        $pos += strlen($start);
        foreach($plugins as $plugin) {
            if(substr($text, $pos, strlen($plugin)) === $plugin
               && ($endPos = strpos($text, $end, $pos + strlen($plugin))) !== false) {
                $char = substr($text, $pos + strlen($plugin), 1); // 1 is strlen of (= or ' ')
                $pos += strlen($plugin) + 1; // 1 is strlen of (= or ' ')
                $argString = substr($text, $pos, $endPos - $pos);
                if($char === ' ') { //Multi arg
                    $params = explode('|', trim($argString));
                    $paramDict = array();
                    foreach ($params as $param) {
                        list($k, $v) = array_pad(explode('=', $param), 2, null);
                        $paramDict[$k] = $v;
                    }
                    //$output = $plugin->processDictionary($paramDict);
                    var_dump($paramDict);
                } elseif ($char === '=') { //One arg
                    //$output = $plugin->processArg($argString); 
                    echo $argString . "\n";
                } elseif ($char === $end) { //No arg
                    //$output = $plugin->processNoArg();
                    echo $plugin. "\n";
                }
                $pos = $endPos + strlen($end);
                break;
            }
        }
    }
}

processPlugins('{plugin1}');
processPlugins('{plugin2=3}');
processPlugins('{plugin2 arg1=b|arg2=d}');

前面的代码在 PHP 沙箱中工作。

这段代码似乎工作(目前),但它似乎粗略。 你会以不同的方式处理这个问题吗? 我可以以某种方式重构这段代码吗?

如果您选择字符串操作函数而不是正则表达式,为什么不使用explode将输入剥离到重要部分?

这是一个替代实现:

function processPlugins($text, $pos = 0, $start = '{', $end = '}') {
  
  $t = substr($text, $pos);
  if($pos > 0) {
    echo "$pos chracters removed from the begining: $t" . PHP_EOL;
  } else {
    echo "Starting with '$t'" . PHP_EOL;
  }
  
  $parts = explode($start, $t);
  $t = $parts[1];
  
  $parts = explode($end, $t);
  $t = $parts[0];

  echo "The part between curly braces: '$t'" . PHP_EOL;
  
  $t = str_replace(['plugin1', 'plugin2'], '', $t);
  
  echo "After plugin name has been removed: '$t'" . PHP_EOL;
  
  $n = strlen($t);  
  if(!$n) {
    echo "Processing complete: " . trim($parts[0]) . PHP_EOL . PHP_EOL;
    return;
  }
  
  $params = explode('|', $t);
  echo 'Key-Values: ' . json_encode($params) . PHP_EOL;
  
  
  $kv = [];
  foreach($params as $p) {
    list($k, $v) = explode('=', trim($p));
    echo "    Item: '$p', Key: '$k', Value: '$v'" . PHP_EOL;
    
    if($k === '') {
      echo "Processing complete: $v" . PHP_EOL . PHP_EOL;
      return;
    }
    
    $kv[$k] = $v;
    
  }
  
  echo "Processing complete: " . json_encode($kv) . PHP_EOL . PHP_EOL;  
  
}

echo '<pre>';
processPlugins('{plugin1}');
processPlugins('{plugin2=3}');
processPlugins('{plugin2 arg1=b|arg2=d}');

当然,回声线可以扔掉。 有了它们,我们得到了这个输出:

Starting with '{plugin1}'  
The part between curly braces: 'plugin1'  
After plugin name has been removed: ''  
Processing complete: plugin1 
 
Starting with '{plugin2=3}' 
The part between curly braces: 'plugin2=3'
After plugin name has been removed: '=3' 
Key-Values: ["=3"]
    Item: '=3', Key: '', Value: '3' 
Processing complete: 3

Starting with '{plugin2 arg1=b|arg2=d}' 
The part between curly braces: 'plugin2 arg1=b|arg2=d' 
After plugin name has been removed: 'arg1=b|arg2=d' 
Key-Values: [" arg1=b","arg2=d"]
    Item: ' arg1=b', Key: 'arg1', Value: 'b'
    Item: 'arg2=d', Key: 'arg2', Value: 'd' 
Processing complete: {"arg1":"b","arg2":"d"}

此版本适用于具有多个插件令牌的输入。

function processPlugins($text, $pos = 0, $start = '{', $end = '}') {
  $processed = [];
  $t = substr($text, $pos);
  $parts = explode($start, $t);
  array_shift($parts);
  foreach($parts as $part) {
    $pparts = explode($end, $part);
    $t = trim($pparts[0]);
    $t = str_replace(['plugin1', 'plugin2'], '', $t);
    $n = strlen($t);
    if(!$n) {
      $processed[] = trim($pparts[0]);
      continue;
    }
    $params = explode('|', $t);
    $kv = [];
    foreach($params as $p) {
      list($k, $v) = explode('=', trim($p));
      if(trim($k) === '') {
        $processed[] = trim($v);
        continue 2;
      }
      $kv[trim($k)] = trim($v);
    }
    $processed[] = $kv;  
  }
  return $processed;
}

function test($case) {
  $p = processPlugins($case);
  echo "$case => " . json_encode($p) . PHP_EOL;
}

$cases = [
  '{plugin1}',
  '{plugin2=3}',
  '{plugin2 arg1=b|arg2=d}',
  'text here {plugin1} and more{plugin2=55}here {plugin2 arg1=b|arg2=d} till the end'
];
foreach($cases as $case) {
  test($case);
}

输出:

{plugin1} => ["plugin1"]
{plugin2=3} => ["3"]
{plugin2 arg1=b|arg2=d} => [{"arg1":"b","arg2":"d"}]
text here {plugin1} and more{plugin2=55}here {plugin2 arg1=b|arg2=d} till the end => ["plugin1","55",{"arg1":"b","arg2":"d"}]

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM