我想对字符串执行此搜索和替换,例如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;
令我极为沮丧的是,结果保持不变。我做错了什么,我应该如何取得正确的结果呢?
答案 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);
正如您所看到的,这种“扫过”字母表:a
被d
取代,后来d
被替换为g
,后来{ {1}}被g
取代。问题在于,当您用j
替换d
时,无论g
代表原来的d
还是原来的d
,您都会这样做a
。每个str_replace
都在丢弃信息;在第一行之后,您无法判断字符串ddd
最初是add
还是原来dad
,当您将d
更改为g
时,得到ggg
而不是dgg
或gdg
或其他。
只有一个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;
解决方案是使用strtr
。方法如下:
$replacePairs = array_combine($search, $replace);
echo strtr('password', $replacePairs); // => sdvvzrug
注意: 不要尝试推出自己的加密算法或协议; 非常容易出错。使用经过试用和测试的库。有关您不应推出自己的加密算法的原因,请参阅this security.SE post。