替换特殊模式之间的大写字母

Replace uppercase letters between special pattern

我喜欢用相同长度的“#”替换“#”之间的字母“KELLY”。 (这里,重复五个 # 而不是 'KELLY')

$str = "####KELLY#####";   // any alpabet letters can come.
preg_replace('/(#{3,})[A-Z]+(#{3,})/', "", $str);

它 returns #########(四个哈希值然后五个哈希值)没有 'KELLY'。

我怎样才能得到 ############## 这是四个原始的前导哈希值,然后用一个哈希值替换每个字母,然后是五个原始的尾随哈希值?

我用 php 中的 preg_replace_callback 函数解决了这个问题。 感谢 CBroe 的提示。

preg_replace_callback('/#{3,}([A-Z]+)#{3,}/i', 'replaceLetters', $str);

function replaceLetters($matches) {
    $ret = '';
    for($i=0; $i < strlen($matches[0]); $i++) {
        $ret .= "#"; 
    }
    return $ret;
}

\G continue 元字符使模式更加混乱,但它能够使用 preg_replace() 而不是 preg_replace_callback()

实际上,它寻找前导的三个或更多哈希值,然后进行单字母替换,直到它到达三个或更多哈希值的结束序列。

该技术还允许“共享”散列标记——我实际上不知道这是否是我们想要的。

代码:(Demo)

$str = "####KELLY##### and ###ANOTHER###### not ####foo#### but: ###SHARE###MIDDLE###HASHES### ?";
echo $str . "\n";
echo preg_replace('/(?:#{3}|\G(?!^))\K[A-Z](?=[A-Z]*#{3})/', '#', $str);

输出:

####KELLY##### and ###ANOTHER###### not ####foo#### but: ###SHARE###MIDDLE###HASHES### ?
############## and ################ not ####foo#### but: ############################# ?

细分:

/               #starting pattern delimiter
(?:             #start non-capturing group
  #{3}          #match three hash symbols
  |             # OR
  \G(?!^)       #continue matching, disallow matching from the start of string
)               #close non-capturing group
\K              #forget any characters matched up to this point
[A-Z]           #match a single letter
(?=             #lookahead (do not consume any characters) for...
    [A-Z]*      #zero or more letters then
    #{3}        #three or more hash symbols
)               #close the lookahead
/               #ending pattern delimiter

或者您可以使用 preg_replace_callback() 获得相同的结果。

代码:(Demo)

echo preg_replace_callback(
         '/#{3}\K[A-Z]+(?=#{3})/',
         function($m) {
             return str_repeat('#', strlen($m[0]));
         },
         $str
     );