【问题标题】:Recursive PHP Function to Replace Characters用于替换字符的递归 PHP 函数
【发布时间】:2011-09-03 18:21:29
【问题描述】:

我正在尝试开发一个递归函数,我可以使用它来去除包含多个值的一串实例。

这是我目前所拥有的:

$words = 'one__two_"__three';

$words = stripall(array('__', '"'), '_', $words);

echo $words;

function stripall($values, $replace, $string) {
            
    foreach ($values as $value) {
        
        if (strpos($string, $value)) {
            
            $string = str_replace($value, $replace, $string);
            
            stripall($values, $replace, $string);
        }
    }
    
    return $string;
}

这里 $words 字符串被去掉了两个下划线 (__) 或引号 (") 的所有实例。或者至少在理论上......

目标返回值为:

one_two_three

但是,我得到的是“one_two___three”

【问题讨论】:

  • 它是因为有一个_,后跟一个",过滤后变成_,然后有一个__,它变成_,导致@ 987654328@ -- 只需将函数内的stripall($values, $replace, $string); 更改为:return stripall($values, $replace, $string); 即可使用

标签: php string function recursion replace


【解决方案1】:
$words = 'one__two_"__three';
$words = stripall(array('"','__'), '_', $words);
echo $words;
function stripall($values, $replace, $string) {
    foreach ($values as $value) {
        while (strpos($string, $value)) {
            $string = str_replace($value, $replace, $string);
            stripall($values, $replace, $string);
        }
    }
    return $string;
}

将 IF 更改为 While 并首先删除 ",然后检查 __

【讨论】:

  • while(strpos(...)) 可以评估为 while(0) 将退出循环,并且不应该。 strpos docs 明确表示要使用 === false 进行测试
【解决方案2】:

我对您的预期输出有点困惑:

one_two_three

假设你的字符串:

$words = 'one__two_"__three';

还有你的规则:

这里 $words 字符串正在获取 剥夺了两个的所有实例 下划线 (__) 或引号 (")

我们会像这样剥离字符串:

$words = 'one[__]two_["][__]three';

所以你的预期输出应该是:

onetwo_three

使用str_replace的数组形式:

$words = 'one__two_"__three';
echo str_replace(array('"', "__"), "", $words) . "\n";

我得到的正是那个输出:

$ php test.php
onetwo_three

【讨论】:

  • 可能他的意思是用"_"替换所有"__"
  • 是的,Jaitsu 明白了。我正在尝试用单曲替换所有双下划线。我可能有一个带有多个下划线的字符串,并且我希望将所有连续的下划线替换为一个。 Onteria,如果我运行你所做的,我会得到“one_two___three”(注意三个下划线)
【解决方案3】:

你想试试我的吗?

//Example:
/*
    $data = strReplaceArrayRecursive(
        array('{name}'=>'Peter','{profileImg}'=>'./PRF-AAD036-51dc30ddc4.jpg'),
        array(
            'title'=>'My name is {name}',
            'post'=>array(
                'author' => '{name}',
                'image' => '{profileImg}',
                'content' => 'My post.'
            )
        )
    );
    print_r($data);
//Expect:
Array
(
    [title] => My name is Peter
    [post] => Array
        (
            [author] => Peter
            [image] => ./PRF-AAD036-51dc30ddc4.jpg
            [content] => My post.
        )

)
*/
function strReplaceArrayRecursive($replacement=array(),$strArray=false,$isReplaceKey=false){
    if (!is_array($strArray)) {
        return str_replace(array_keys($replacement), array_values($replacement), $strArray);
    }
    else {
        $newArr = array();
        foreach ($strArray as $key=>$value) {
            $replacedKey = $key;
            if ($isReplaceKey) {
                $replacedKey = str_replace(array_keys($replacement), array_values($replacement), $key);
            }
            $newArr[$replacedKey] = strReplaceArrayRecursive($replacement, $value, $isReplaceKey);
        }
        return $newArr;
    }
}

【讨论】:

    【解决方案4】:

    我认为没有人可以说服我为此使用循环或非正则表达式方法。如果有人不使用正则表达式,我会假设他们根本不了解对不同字符序列执行替换的功能和实用性。

    该模式仅扫描输入字符串并替换一个或多个下划线和/或双引号的所有序列。

    这种技术唯一不必要的副作用(但不会对结果产生负面影响)是它会不必要地用单个下划线替换单个下划线。理想情况下,不应将模式设计为​​进行不必要的匹配/替换,但在这种情况下,它不需要对字符串进行第二次扫描以清除任何新生成的连续下划线。

    只需一个函数调用就可以完美地整理您的文本——这正是正则表达式存在的原因。

    代码:(Demo)

    $strings = [
        'one"two_"_"_three',
        'one__two_"__three',
        'one__two_"__""____"three',
        'one__two___"""""""______three',
    ];
    
    var_export(
        preg_replace('~["_]+~', '_', $strings)
    );
    

    输出:

    array (
      0 => 'one_two_three',
      1 => 'one_two_three',
      2 => 'one_two_three',
      3 => 'one_two_three',
    )
    

    【讨论】:

    • 我没有 dv 但我只会考虑 preg* 一个 "lean" 解决方案,如果您所说的精益是指 "lean on",像拐杖。 Fwiw 您的表达式数组可以简化为单个表达式,应用时不依赖于顺序:preg_replace('/["_]+/', '_', $strings)
    • 我称它为“精益”,因为它是直接执行的。我同意你的模式建议,显然我是_over-thinking它,所以我会更新我的答案。干杯@Tha 幸运的是,我的攻击者已经从我的回答中走出来了,现在正在对我的问题执行一个非常审慎/受控的每日 DV——而且我没有很多问题要攻击:)。
    • SO 非常擅长检测所谓的serial down-voting。我很好奇你对preg* 的理解,因为它们的用途不是direct。有一个完整的语法、词法分析器、解析器和求值器来支持正则表达式操作。从初学者的角度来看,正则表达式“引擎”是一顶神奇的帽子,看起来很有趣的字符串进入其中,答案神秘地弹出。除非您对语法和功能有深入的了解,否则很难调试。
    • 我对正则表达式非常满意,所以我不认为它是魔法。我认为在这种情况下非常合适。如果您认为单个 preg_ 调用不是直接的,那么我担心您对正则表达式有偏见。根据我的经验,SO 很难检测到连续投票,然后当它检测到时,它只是将分数返回给罪犯,然后他们学会调整攻击速度,这样 SO 脚本就不会检测到它。在这种情况下,影响不仅仅是我帖子上的 DV,还有其他帖子上的 UV(我不会认可)——所有这些都是为了让研究人员远离我的建议。
    【解决方案5】:

    这个功能完全没有必要。 str_replace 已经做了同样的事情。

    【讨论】:

    • 错误。如果我以这种方式运行它,我仍然会得到带有三个下划线的“one_two___three”的结果。
    • 你可以使用 preg_replace_callback 代替 str_replace
    • 没有正当理由使用preg_replace_callback() 完成此任务。
    猜你喜欢
    • 2011-05-09
    • 2020-07-19
    • 2012-11-16
    • 2016-04-09
    • 2012-04-19
    • 2011-09-27
    • 1970-01-01
    • 2017-04-24
    • 1970-01-01
    相关资源
    最近更新 更多