具有相同数量的星的检查词比词长

时间:2011-03-28 21:25:40

标签: php regex preg-replace

我想用星星替换1或2个字符的所有单词。 我目前使用此规则:

$validTxt = preg_replace("/\\b\\w{1,2}\\b/", '*', $validTxt);

但是当单词有2个字符时,它只被1个星号代替,而不是2个星号。 我需要一种快速的方法来做到这一点。即使需要100行代码,性能也是优先考虑的事项。

6 个答案:

答案 0 :(得分:3)

$validTxt = preg_replace_callback(
    '~\b\w{1,2}\b~',
    function($matches) { return str_repeat('*', strlen($matches[0])); },
    $validTxt
);

这样做的好处是您可以更改限制{1,2},而无需调整某些正则表达式=>替换阵列。

答案 1 :(得分:1)

呃,两次传球只是我的第一个想法:

$validTxt = preg_replace('/\b\w{1}\b/', '*', $validTxt);

$validTxt = preg_replace('/\b\w{2}\b/', '**', $validTxt);

但我在正则表达式上生锈了,不知道是否有更好的方法。

编辑:因为我看到你可以传递一个数组,所以我正在扩展这个解决方案:

$pattern = array();
$pattern[0] = '/(\b)\w{1}(\b)/';
$pattern[1] = '/(\b)\w{2}(\b)/';

$replace = array();
$replace[0] = '$\0*$\1';
$replace[1] = '$\0**$\1';

$validTxt = preg_replace($pattern, $replace, $validTxt)

好的,应该还保留旧文本周围的空白,这意味着顺序无关紧要。但是如果你想替换空格,你需要修改代码。

答案 2 :(得分:1)

好吧试试这个:

$p = array();
$p[0] = '/\b\w{1}\b/';
$p[1] = '/\b\w{2}\b/';

$r = array();
$r[0] = '*';
$r[1] = '**';

echo preg_replace($p, $r, "a") . "\n"; // prints *
echo preg_replace($p, $r, "ab") . "\n"; // prints **

答案 3 :(得分:1)

提取'e'修饰符的完美时间,允许您将可执行代码放入替换字符串中。 (请注意,此'e'修饰符只能与preg_replace()一起使用。)此测试函数可以解决这个问题:

function words_to_stars($text) {
    $replace = 'str_repeat("*", strlen("$0"));';
    return preg_replace('/\b\w{1,2}\b/e', $replace, $text);
}

请注意,这个方法不会像nikic的回调解决方案那么快,但我想我会把这个答案放到ring anyoo中(因为很多人可能不知道这个方便的功能。)

更新:基准,哦,我的! 我很好奇哪种方法最快,多少,所以我只是使用我漂浮的方便基准函数来测量各种方法的速度。我采用了三种方法中的每一种,并创建了一个功能来干净地实现每个方法。 (请注意,我必须修改Nikic的解决方案,因为我的PHP 5.2.14不喜欢将函数直接放入preg_replace_callback()参数的语法。)以下是测量的函数:

// Ridgerunner's "e_modifier" method:
function words_to_stars_e_modifier($validTxt) {
    return preg_replace('/\b\w{1,2}\b/e',
        'str_repeat("*", strlen("$0"));',
        $validTxt);
}

// nikic's "callback" method (modified):
function words_to_stars_callback($validTxt) {
    return preg_replace_callback('~\b\w{1,2}\b~',
        '_words_to_stars_callback',
        $validTxt);
}
function _words_to_stars_callback($matches) {
    return str_repeat('*', strlen($matches[0]));
}

// Eva611, Matt and anubhava's "array" method:
function words_to_stars_array($validTxt) {
    return preg_replace(
        array('/\b\w{1}\b/', '/\b\w{2}\b/'),
        array('*',            '**'),
        $validTxt);
}

我从这个网页上获取了文本作为测试数据,然后测量了每个函数用了多长时间来完成它的工作(在我的AMD64 3700+ Win32 XP盒子上)。以下是基准测试的结果:( Drumroll,拜托!)

e_modifier() Nreps: 133  Time: 1.050 s  Function time: 0.007893 sec
callback()   Nreps: 213  Time: 1.034 s  Function time: 0.004856 sec
array()      Nreps: 578  Time: 1.016 s  Function time: 0.001758 sec

我怀疑,'e'修饰符方法最慢。回调方法排在第二位,而Eva611,Matt和anubhava的阵列方法以压倒性优势获胜!

答案 4 :(得分:0)

// you can pass arrays in preg_replace
$pattern = array();
$censor = array();
$pattern[0] = '/\b\w{1}\b/';
$pattern[1] = '/\b\w{2}\b/';
$censor[0] = '*';
$censor[1] = '**';

$validTxt = preg_replace($pattern, $replace, $validTxt)

答案 5 :(得分:-2)

只是一个想法,但你可能能够使用一个匹配组,然后用str_repeat包裹它的strlen:

$validTxt = preg_replace("/\\b(\\w{1,2})\\b/", str_repeat('*', str_len("$1")), $validTxt);

我目前无法访问PHP dev env,因此未经测试。