用不同的字母替换字母

问题描述 投票:0回答:3

我必须将旧的 Perl 脚本升级到 php。该脚本对密码进行一些编码以存储在我们的数据库中,如下所示:-

$pw =~ tr/a-zA-Z/h-za-gH-ZA-G/;

因此 /a-zA-Z/ 中的每个字母都被 /h-za-gH-ZA-G/ 中的等效字母替换

我正在尝试找到一种在 PHP 中执行相同操作的方法?

我查看了 str_replace 但这似乎涉及编写一个长数组而不是像 perl 这样的替换模式

php replace caesar-cipher
3个回答
3
投票

一般来说该函数称为 strtr():

strtr($string, $from, $to);

这种形式有三个参数:

$string
将被翻译,返回值是翻译后的字符串。

这里

$from
$to
包含要从 -> 转换到的字节,因此两个字符串应该具有相同的字节大小(参见 strlen())。

$secret = strtr(
  $plain,
  'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', 
  'hijklmnopqrstuvwxyzabcdefgHIJKLMNOPQRSTUVWXYZABCDEFG',
);

现在,与 Perl 翻译运算符相比,该函数的不同之处在于,您没有 26 个字节的内部短格式

a-z

为此,您可以使用 range() 函数,它也适用于字节(字符),但是它返回一个数组,然后您可以内爆或使用带有两个参数的 strtr(),仅当第二个参数是数组。

$string = "hello, world!\n";

$from = range('a', 'z');
$to = [...range('h', 'z'), ...range('a', 'g')];

echo strtr($string, array_combine($from, $to)); // olssv, dvysk!

使用数组的第二种形式具有额外的好处,您可以替换多个字节,也可以替换不同长度的字节(例如 UTF-8)。但请注意,range() 与手册中的内容不兼容:

如果 startend 是具有多个字节的非数字字符串,则会发出 E_WARNING。

请参阅手册页了解所有详细信息:


没有找到大象PHP代码格式器并且不想深入搜索,这里是可以将模式作为字符串进行操作的函数,如上所述:

$string = "hello, world!\n";

$fn = fn(string $string, string $pattern) => strtr(
    $string,
    array_combine(
        ...array_map(fn(string $ranges) => array_merge(
        ...array_map(fn(string $range) => range(
        ...sscanf($range, '%[^-]-%[^-]')), str_split($ranges, 3))),
        sscanf($pattern, 'tr/%[^/]/%[^/]/'))));

echo $fn($string, 'tr/a-zA-Z/h-za-gH-ZA-G/'); // olss, dvysk!

虽然 PHP 中有 Perl 兼容的正则表达式 (PCRE),但此示例未使用任何 preg_*() 函数。


1
投票

我尝试创建一些相对容易阅读的代码:

<?php

function getRanges(array $pairs): string
{
    $result = '';
    foreach ($pairs as $pair) {
        [$start, $finish]  = $pair;
        $result .= implode('', range($start, $finish));
    }    
    return $result;
}

function perlReplace(string $input): string
{
    return strtr($input, 
                 getRanges([['a', 'z'], ['A', 'Z']]), 
                 getRanges([['h', 'z'], ['a', 'g'], ['H', 'Z'], ['A', 'G']]));
}    

echo perlReplace('My PassWord');

这将返回

Tf WhzzDvyk
。这和 hakre 刚才的回答非常相似。

现场演示:https://3v4l.org/ZhZgN

呃,我需要指出这是一种在数据库中存储密码的非常糟糕的方法吗?看看 password_hash()。提高安全性永远不会太晚。


0
投票

如果你想在 php 中创建一个简单的加密映射,你可以使用 strtr() 函数,如下所示:

$password = 'GooglePleaseLetMeBeOneOfYourIntern'
$from = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$to = 'hijklmnopqrstuvwxyzabcdefgHIJKLMNOPQRSTUVWXYZABCDEFG';
return strtr($password, $from, $to); //return the password crypted by the mapping
最新问题
© www.soinside.com 2019 - 2025. All rights reserved.