$string='print the imprint with the imprinted printing paper';
$pattern=array('/print/','/imprint/','/paper/',);
$replacement=array('imprint','print','machine');
输出:
print the imprint with the imprinted printing machine
我认为我理解正确的前两种模式相互重叠。我想让这个更复杂,但REGEX仍然是我的伏都教。显示输入字符串后,我想回复一下:imprint the print with the printed imprinting machine
。如果我还能看到如何输出imprint the print with the imprinted printing machine
,那也会很棒。
如果你能解释一下你的正则表达式,那会更有帮助。也许我以后可以自己做更多的事情。
答案 0 :(得分:4)
在单个正则表达式中完成所有这些替换,并且您没问题,因为在一次传递中,正则表达式将在一次替换后继续,并且不会再次尝试与替换匹配:
$string = 'print the imprint with the imprinted printing paper';
// A single array of find => replace
$replacements = array(
'print' => 'imprint',
'imprint' => 'print',
'paper' => 'machine'
);
// Dynamically form the regex, properly escaping it
$delimiter = '/';
$words = array_keys( $replacements);
$regex = $delimiter . '\b(' . implode('|', array_map( 'preg_quote', $words, array_fill( 0, count( $words), $delimiter))) . ')\b' . $delimiter;
形成的正则表达式如下所示:
/\b(print|imprint|paper)\b/
其中:
\b
是一个单词边界。()
是一个捕获组。print|imprint|paper
是一个或匹配其中一个最后,要做替换:
$result = preg_replace_callback( $regex, function( $match) use( $replacements) {
return $replacements[$match[1]];
}, $string);
echo $result;
imprint the print with the printed imprinting machine
答案 1 :(得分:2)
如果您需要进行直接的字符串替换,而不是多次重复结果字符串,则应使用strtr()
代替:
strtr($string, array(
'imprint' => 'print',
'print' => 'imprint',
'paper' => 'machine',
));
要替换的单词按字符串长度排序,最具体的是第一个。
注意:这当然不像正则表达式那样灵活,特别是当它只替换完整的单词时,即/\bword\b/
仅匹配word
时才会匹配;这不是你可以用strtr()
和朋友做的事情。
使用正则表达式
要使preg_replace()
只对字符串执行一次传递,您需要将替换键组合成一个表达式,即
/imprint|print|paper/
此表达式使用交替,由搜索字符串之间的管道字符影响。要仅匹配整个单词,您需要添加边界匹配,一个特殊的\b
序列,匹配单词和非单词之间的过渡。
/\b(?:imprint|print|paper)\b/
这将匹配"imprint"
但不匹配"pimprint"
。
如果您沿着这条路线行驶,则需要使用preg_replace_callback()
执行更换;对于每个匹配,它会找到一个自定义函数,您可以在其中确定要替换它的内容。你需要为它创建一个替换地图,就像我之前用于strtr()
示例的地图一样。
$map = array(
'imprint' => 'print',
'print' => 'imprint',
'paper' => 'machine',
);
$replacer = function($match) use ($map) {
// $match[0] holds the found word
return $map[$match[0]];
};
preg_replace_callback('/\b(?:imprint|print|paper)\b/', $string, $replacer);
让它变得动态
我已经手动创建了正则表达式,但为了使其灵活,您需要根据替换映射动态生成它。为此,我们需要:
这就是构建表达式的方法:
// step 1
$replacement_keys = array_keys($map);
// step 2
$escaped_keys = array_map(function($key) {
return preg_quote($key, '/');
}, $replacement_keys);
// step 3
$pattern = '/\b(?:' . join('|', $escaped_keys) . ')\b/';