如何将“a”替换为“d”,将“b”替换为“e”,将“c”替换为“f”,. 。 。 “x”表示“a”,“y”表示“b”,“z”表示“c”?

时间:2014-01-18 06:41:26

标签: php arrays str-replace

我想对字符串执行此搜索和替换,例如password

正如您可以从问题中理解的那样,在替换后,字符串应变为sdvvzrug

但不幸的是,以下代码输出bbbbcaab

$search = range("a", "z");
$replace = array_merge(range("d", "z"), range("a", "c"));
echo str_replace($search, $replace, "password");

这可能导致什么问题?起初我怀疑在str_replace中使用数组,因此我使用了一个循环并尝试一次替换一个字符:

$search = range("a", "z");
$replace = array_merge(range("d", "z"), range("a", "c"));
$str = "password";
    for($i = 0; $i < 26; $i++)
    {
    $str = str_replace($search[$i], $replace[$i], $str);
    }
echo $str;

令我极为沮丧的是,结果保持不变。我做错了什么,我应该如何取得正确的结果呢?

4 个答案:

答案 0 :(得分:3)

执行此多次更换是错误的。使用strtr将解决问题,因为它不会更改已替换的字符。

这就是你如何得到bbbbcaab:

    :password
a->d:pdssword
b->e:pdssword
c->f:*
d->g:pgssworg
e->h:*
f->i:*
g->j:pjssworj
h->k:*
i->l:*
j->m:pmssworm
k->n:*
l->o:*
m->p:ppssworp
n->q:*
o->r:ppsswrrp
p->s:sssswrrs
q->t:*
r->u:sssswuus
s->v:vvvvwuuv
t->w:*
u->x:vvvvwxxv
v->y:yyyywxxy
w->z:yyyyzxxy
x->a:yyyyzaay
y->b:bbbbzaab
z->c:bbbbcaab

答案 1 :(得分:2)

其他答案已经解释了如何做到这一点,所以我将重点关注“我做错了什么?”一部分。

所以,你的for - 循环等同于:

$str = str_replace('a', 'd', $str);
$str = str_replace('b', 'e', $str);
$str = str_replace('c', 'f', $str);
$str = str_replace('d', 'g', $str);
$str = str_replace('e', 'h', $str);
$str = str_replace('f', 'i', $str);
$str = str_replace('g', 'j', $str);
// ...
$str = str_replace('z', 'c', $str);

正如您所看到的,这种“扫过”字母表:ad取代,后来d被替换为g,后来{ {1}}被g取代。问题在于,当您用j替换d时,无论g代表原来的d还是原来的d,您都会这样做a。每个str_replace都在丢弃信息;在第一行之后,您无法判断字符串ddd最初是add还是原来dad,当您将d更改为g时,得到ggg而不是dgggdg或其他。

只有一个str_replace的版本具有相同结果的原因是str_replace与循环做同样的事情:它只是迭代搜索数组,执行替换,并且不会确保它永远不会“重新替换”子串。这就是为什么你需要使用专为此目的而设计的strtr等方法。

答案 2 :(得分:1)

我们走了,

$search = range("a", "z");
$replace = array_merge(range("d", "z"), range("a", "c"));
$str = "password";
$newstr = '';
for($i = 0; $i < strlen($str); $i++)
{
    $key = array_search($str[$i],$search);
    $newstr .= $replace[$key]; 
}    
echo $newstr;

<强> DEMO.

答案 3 :(得分:1)

str_replace按顺序执行所有替换,无论字符串是派生值还是新值。使用strtr代替一次性完成所有替换:

来自documentation for str_replace

  

更换订单

     

因为str_replace()从左向右替换,所以在进行多次替换时,它可能会替换先前插入的值。

我对您的for循环进行了一些修改,以帮助您了解如何获得该输出:

<?php

$str = "password";
$search = range("a", "z");
$replace = array_merge(range("d", "z"), range("a", "c"));

header('Content-Type: text/plain');

for($i = 0; $i < 26; $i++)
{
    $beforeStr = $str;
    $str = str_replace($search[$i], $replace[$i], $str);

    //var_dump($search[$i], $replace[$i], $str);

    if ($beforeStr !== $str) {
        echo "$i) $search[$i] -> $replace[$i]\n";
        echo "Replacement: $before -> $str";
    } else {
        echo "$i) $search[$i] -> $replace[$i]\n";
        echo "Replacement: none";
    }
    echo "\n\n";
}

echo $str;

Demo

解决方案是使用strtr。方法如下:

$replacePairs = array_combine($search, $replace);
echo strtr('password', $replacePairs); // => sdvvzrug

Demo


注意: 不要尝试推出自己的加密算法或协议; 非常容易出错。使用经过试用和测试的库。有关您不应推出自己的加密算法的原因,请参阅this security.SE post