RMa*_*tin 11 php regex preg-replace
我在下面有以下数据{n}代表一个占位符.
{n}{n}A{n}{n}A{n}
{n}A{n}{n}{n}{n}A
{n}{n}A{n}A{n}{n}
{n}{n}{n}A{n}A{n}B
{n}A{n}{n}B{n}{n}
A{n}B{n}{n}{n}{n}
Run Code Online (Sandbox Code Playgroud)
我想用两个A字符替换占位符的每个实例,例如字母C.我为此编写了以下正则表达式,我正在使用preg_replace函数.
$str = preg_replace('~(?<=A)(\{n\})*(?=A)~', 'C', $str);
Run Code Online (Sandbox Code Playgroud)
问题是它将两个A之间的所有实例替换为一个C.我怎样才能修复我的正则表达式或preg_replace调用以替换占位符的每个单独实例C?
这应该是我的输出.
{n}{n}ACCA{n}
{n}ACCCCA
{n}{n}ACA{n}{n}
{n}{n}{n}ACA{n}B
{n}A{n}{n}B{n}{n}
A{n}B{n}{n}{n}{n}
Run Code Online (Sandbox Code Playgroud)
但目前它输出了这个.
{n}{n}ACA{n}
{n}ACA
{n}{n}ACA{n}{n}
{n}{n}{n}ACA{n}B
{n}A{n}{n}B{n}{n}
A{n}B{n}{n}{n}{n}
Run Code Online (Sandbox Code Playgroud)
您可以通过锚定来解决问题\G.
$str = preg_replace('~(?:\G(?!\A)|({n})*A(?=(?1)++A))\K{n}~', 'C', $str);
Run Code Online (Sandbox Code Playgroud)
该\G功能是一个可以在两个位置之一匹配的锚点; 字符串位置的开头或最后一个匹配结束时的位置.该\K转义序列重置报道比赛的出发点和任何先前消耗字符不再包括在内.
要减少回溯量,可以使用更复杂的表达式:
$str = preg_replace('~\G(?!\A)(?:{n}
|A(?:[^A]*A)+?((?=(?:{n})++A)\K{n}
|(*COMMIT)(*F)))
|[^A]*A(?:[^A]*A)*?(?1)~x', 'C', $str);
Run Code Online (Sandbox Code Playgroud)
更详细但更容易理解的解决方案是使用初始表达式将文本分成组; 然后在每个组中应用单个转换:
$text = preg_replace_callback('~(?<=A)(?:\{n\})*(?=A)~', function($match) {
// simple replacement inside
return str_replace('{n}', 'C', $match[0]);
}, $text);
Run Code Online (Sandbox Code Playgroud)
我已经对表达式进行了一些小调整,以消除内存捕获,这是不必要的,通过使用(?:...).