如何重构函数以将 preg_replace_callback() 与多个正则表达式字符串和多个数组中的替换字符串一起使用?
How to refactor a function to use preg_replace_callback() with multiple regex strings and replacement strings in multiple arrays?
我正在重构一些遗留 PHP 代码(5.5 版),我需要重构一个函数以使用 preg_replace() 中的 preg_replace_callback()(这是因为\e 评估弃用)但是传递给仅有的 2 个 preg_replace() 调用的是搜索模式数组和替换数组。
我知道我需要将回调函数传递给 preg_replace_callback(),但是当每个模式不同时,如何处理这个问题?
function format($in, $options = 0)
{
if (!$options) {
$options = FORMAT_BREAKS | FORMAT_HTMLCHARS | FORMAT_CENSOR;
}
if ($options & FORMAT_CENSOR) {
if (!$this->replaces_loaded) {
$this->get_replaces();
}
if ($this->censor) {
$in = preg_replace($this->censor, '####', $in);
}
}
if ($options & FORMAT_MBCODE) {
$search = array(
'~(^|\s)([a-z0-9-_.]+@[a-z0-9-.]+\.[a-z0-9-_.]+)~i',
'~(^|\s)(http|https|ftp)://(\w+[^\s\[\]]+)~ise'
);
$replace = array(
'\1[email]\2[/email]',
'\'\1[url]\' .wordwrap(\'\2://\3\', 1, \' \', 1) . \'[/url]\''
);
$brackets = (strpos($in, '[') !== false) && (strpos($in, ']') !== false);
if ($brackets) {
$b_search = array(
'~\[code](.*?)\[/code]~ise',
'~\[php](.*?)\[/php]~ise',
'~\[php=([0-9]+?)](.*?)\[/php]~ise',
'~\[img](http|https|ftp)://(.*?)\[/img]~ise',
'~\[url](.*?)\[/url]~ise',
'~\[url=(http|https|ftp)://(.+?)](.+?)\[/url]~ise'
);
$b_replace = array(
'\'[code]\' . function (array $matches){ return base64_encode(\'\1\') . \'[/code]\'',
'\'[php]\' . base64_encode(\'\1\') . \'[/php]\'',
'\'[php=\1]\' . base64_encode(\'\2\') . \'[/php]\'',
'\'[img]\' . wordwrap(\'\1://\2\', 1, \' \', 1) . \'[/img]\'',
'\'[url]\' . wordwrap(\'\1\2\', 1, \' \', 1) . \'[/url]\'',
'\'[url=\' . wordwrap(\'\1://\2\', 1, \' \', 1) . \']\3[/url]\''
);
$search = array_merge($search, $b_search);
$replace = array_merge($replace, $b_replace);
error_log(print_r($replace));
}
$in = preg_replace($search, $replace, $in);
$brackets = (strpos($in, '[') !== false) && (strpos($in, ']') !== false); //We may have auto-parsed a URL, adding a bracket
}
$strtr = array();
if ($options & FORMAT_HTMLCHARS) {
$strtr['&'] = '&';
$strtr['"'] = '"';
$strtr['\''] = ''';
$strtr['<'] = '<';
$strtr['>'] = '>';
}
if ($options & FORMAT_BREAKS) {
$strtr["\n"] = "<br />\n";
}
if ($this->user['user_view_emoticons'] && ($options & FORMAT_EMOTICONS)) {
if (!$this->replaces_loaded) {
$this->get_replaces();
}
$strtr = array_merge($strtr, $this->emotes['replacement']);
}
$in = strtr($in, $strtr);
if (($options & FORMAT_MBCODE) && $brackets) {
$search = array(
'~\[(/)?([bi])]~i',
'~\[u]~i',
'~\[s]~i',
'~\[/[us]]~i',
'~\[url](h t t p|h t t p s|f t p) : / /(.+?)\[/url]~ise',
'~\[url=(h t t p|h t t p s|f t p) : / /(.+?)](.+?)\[/url]~ise',
'~\[email]([a-z0-9-_.]+@[a-z0-9-.]+\.[a-z0-9-_.]+)?\[/email]~i',
'~\[email=([^<]+?)](.*?)\[/email]~i',
'~\[img](h t t p|h t t p s|f t p) : / /(.*?)\[/img]~ise',
'~\[(right|center)](.*?)\[/]~is',
'~\[code](.*?)\[/code]~ise',
'~\[php](.*?)\[/php]~ise',
'~\[php=([0-9]+?)](.*?)\[/php]~ise',
'~\[color=(\S+?)](.*?)\[/color]~is',
'~\[font=(.+?)](.*?)\[/font]~is',
'~\[size=([0-9]+?)](.*?)\[/size]~is'
);
$replace = array(
'<\1\2>',
'<span style=\'text-decoration:underline\'>',
'<span style=\'text-decoration:line-through\'>',
'</span>',
'\'<a href="\' . str_replace(\' \', \'\', \'\1://\2\') . \'" onclick="window.open(this.href,\\'' . $this->sets['link_target'] . '\\');return false;">\' . str_replace(\' \', \'\', \'\1://\2\') . \'</a>\'',
'\'<a href="\' . str_replace(\' \', \'\', \'\1://\2\') . \'" onclick="window.open(this.href,\\'' . $this->sets['link_target'] . '\\');return false;">\3</a>\'',
'<a href="mailto:\1">\1</a>',
'<a href="mailto:\1">\2</a>',
'\'<img src="\' . str_replace(\' \', \'\', \'\1://\2\') . \'" alt="\' . str_replace(\' \', \'\', \'\1://\2\') . \'" />\'',
'<div align="\1">\2</div>',
'$this->format_code(\'\1\', 0)',
'$this->format_code(\'\1\', 1)',
'$this->format_code(\'\2\', 1, \'\1\')',
'<span style=\'color:\1\'>\2</span>',
'<span style=\'font-family:\1\'>\2</span>',
'<span style=\'font-size:\1ex\'>\2</span>'
);
if ((substr_count($in, '[quote]') + substr_count($in, '[quote=')) == substr_count($in, '[/quote]')) {
$search[] = '~\[quote=(.+?)]~i';
$search[] = '~\[quote]~i';
$search[] = '~\[/quote]~i';
$replace[] = '<table style="width:90%; margin-left:5%; margin-right:5%;" border="0" cellpadding="3" cellspacing="0"><tr><td><b>\1 ' . $this->lang->main_said . ':</b></td></tr><tr><td class="quote">';
$replace[] = '<table style="width:90%; margin-left:5%; margin-right:5%;" border="0" cellpadding="3" cellspacing="0"><tr><td><b>' . $this->lang->main_quote . ':</b></td></tr><tr><td class="quote">';
$replace[] = '</td></tr></table>';
}
$in = preg_replace_callback($search, $replace, $in);
$in = str_replace(array(' ', "\t", '&#'), array(' ', ' ', '&#'), $in);
}
return $in;
}
我测试了将匿名函数直接放入替换数组的尝试,但收到错误消息:class 闭包的对象无法转换为字符串。但也许我做错了?
$replace = array(
'\1[email]\2[/email]',
"'\'\1[url]\'" . function (array $matches) {return wordwrap($matches[1], $matches[2], $matches[3], $matches[4]); } . " \'[/url]\''"
);
非常感谢您的建议。
创建一个关联数组,其中键包含正则表达式模式,值包含回调(回调没有 prepending/appending 字符串)。
我不会重写我的 phone 中的那个庞然大物,所以我将演示一个替换。
将您的模式和回调数组提供给 preg_replace_callback_array()
。
代码:(Demo)
$patternCallbacks = [
'~\[code](.*?)\[/code]~is' =>
function($m) {
return '[code]' . base64_encode($m[1]) . '[/code]';
},
// add more elements as needed...
];
echo preg_replace_callback_array(
$patternCallbacks,
'This is my [code]script[/code] to display'
);
输出:
This is my [code]c2NyaXB0[/code] to display
编辑,因为你不能使用preg_replace_callback_array()
,你需要重复调用preg_replace_callback()
。
代码:(Demo)
$patternCallbacks = [
'~\[code](.*?)\[/code]~is' =>
function($m) {
return '[code]' . base64_encode($m[1]) . '[/code]';
},
'~\[php(?:=\d+)?]\K(.*?)\[/php]~is' =>
function($m) {
return base64_encode($m[1]) . '[/php]';
},
];
$text = <<<TEXT
This is my [code]script[/code] to display.
It has [php]unnumbered tag
code[/php] and [php=8]numbered tag code[/php].'
TEXT;
foreach ($patternCallbacks as $pattern => $callback) {
$text = preg_replace_callback($pattern, $callback, $text);
}
echo $text;
输出:
This is my [code]c2NyaXB0[/code] to display.
It has [php]dW5udW1iZXJlZCB0YWcKIGNvZGU=[/php] and [php=8]bnVtYmVyZWQgdGFnIGNvZGU=[/php].
我正在重构一些遗留 PHP 代码(5.5 版),我需要重构一个函数以使用 preg_replace() 中的 preg_replace_callback()(这是因为\e 评估弃用)但是传递给仅有的 2 个 preg_replace() 调用的是搜索模式数组和替换数组。
我知道我需要将回调函数传递给 preg_replace_callback(),但是当每个模式不同时,如何处理这个问题?
function format($in, $options = 0)
{
if (!$options) {
$options = FORMAT_BREAKS | FORMAT_HTMLCHARS | FORMAT_CENSOR;
}
if ($options & FORMAT_CENSOR) {
if (!$this->replaces_loaded) {
$this->get_replaces();
}
if ($this->censor) {
$in = preg_replace($this->censor, '####', $in);
}
}
if ($options & FORMAT_MBCODE) {
$search = array(
'~(^|\s)([a-z0-9-_.]+@[a-z0-9-.]+\.[a-z0-9-_.]+)~i',
'~(^|\s)(http|https|ftp)://(\w+[^\s\[\]]+)~ise'
);
$replace = array(
'\1[email]\2[/email]',
'\'\1[url]\' .wordwrap(\'\2://\3\', 1, \' \', 1) . \'[/url]\''
);
$brackets = (strpos($in, '[') !== false) && (strpos($in, ']') !== false);
if ($brackets) {
$b_search = array(
'~\[code](.*?)\[/code]~ise',
'~\[php](.*?)\[/php]~ise',
'~\[php=([0-9]+?)](.*?)\[/php]~ise',
'~\[img](http|https|ftp)://(.*?)\[/img]~ise',
'~\[url](.*?)\[/url]~ise',
'~\[url=(http|https|ftp)://(.+?)](.+?)\[/url]~ise'
);
$b_replace = array(
'\'[code]\' . function (array $matches){ return base64_encode(\'\1\') . \'[/code]\'',
'\'[php]\' . base64_encode(\'\1\') . \'[/php]\'',
'\'[php=\1]\' . base64_encode(\'\2\') . \'[/php]\'',
'\'[img]\' . wordwrap(\'\1://\2\', 1, \' \', 1) . \'[/img]\'',
'\'[url]\' . wordwrap(\'\1\2\', 1, \' \', 1) . \'[/url]\'',
'\'[url=\' . wordwrap(\'\1://\2\', 1, \' \', 1) . \']\3[/url]\''
);
$search = array_merge($search, $b_search);
$replace = array_merge($replace, $b_replace);
error_log(print_r($replace));
}
$in = preg_replace($search, $replace, $in);
$brackets = (strpos($in, '[') !== false) && (strpos($in, ']') !== false); //We may have auto-parsed a URL, adding a bracket
}
$strtr = array();
if ($options & FORMAT_HTMLCHARS) {
$strtr['&'] = '&';
$strtr['"'] = '"';
$strtr['\''] = ''';
$strtr['<'] = '<';
$strtr['>'] = '>';
}
if ($options & FORMAT_BREAKS) {
$strtr["\n"] = "<br />\n";
}
if ($this->user['user_view_emoticons'] && ($options & FORMAT_EMOTICONS)) {
if (!$this->replaces_loaded) {
$this->get_replaces();
}
$strtr = array_merge($strtr, $this->emotes['replacement']);
}
$in = strtr($in, $strtr);
if (($options & FORMAT_MBCODE) && $brackets) {
$search = array(
'~\[(/)?([bi])]~i',
'~\[u]~i',
'~\[s]~i',
'~\[/[us]]~i',
'~\[url](h t t p|h t t p s|f t p) : / /(.+?)\[/url]~ise',
'~\[url=(h t t p|h t t p s|f t p) : / /(.+?)](.+?)\[/url]~ise',
'~\[email]([a-z0-9-_.]+@[a-z0-9-.]+\.[a-z0-9-_.]+)?\[/email]~i',
'~\[email=([^<]+?)](.*?)\[/email]~i',
'~\[img](h t t p|h t t p s|f t p) : / /(.*?)\[/img]~ise',
'~\[(right|center)](.*?)\[/]~is',
'~\[code](.*?)\[/code]~ise',
'~\[php](.*?)\[/php]~ise',
'~\[php=([0-9]+?)](.*?)\[/php]~ise',
'~\[color=(\S+?)](.*?)\[/color]~is',
'~\[font=(.+?)](.*?)\[/font]~is',
'~\[size=([0-9]+?)](.*?)\[/size]~is'
);
$replace = array(
'<\1\2>',
'<span style=\'text-decoration:underline\'>',
'<span style=\'text-decoration:line-through\'>',
'</span>',
'\'<a href="\' . str_replace(\' \', \'\', \'\1://\2\') . \'" onclick="window.open(this.href,\\'' . $this->sets['link_target'] . '\\');return false;">\' . str_replace(\' \', \'\', \'\1://\2\') . \'</a>\'',
'\'<a href="\' . str_replace(\' \', \'\', \'\1://\2\') . \'" onclick="window.open(this.href,\\'' . $this->sets['link_target'] . '\\');return false;">\3</a>\'',
'<a href="mailto:\1">\1</a>',
'<a href="mailto:\1">\2</a>',
'\'<img src="\' . str_replace(\' \', \'\', \'\1://\2\') . \'" alt="\' . str_replace(\' \', \'\', \'\1://\2\') . \'" />\'',
'<div align="\1">\2</div>',
'$this->format_code(\'\1\', 0)',
'$this->format_code(\'\1\', 1)',
'$this->format_code(\'\2\', 1, \'\1\')',
'<span style=\'color:\1\'>\2</span>',
'<span style=\'font-family:\1\'>\2</span>',
'<span style=\'font-size:\1ex\'>\2</span>'
);
if ((substr_count($in, '[quote]') + substr_count($in, '[quote=')) == substr_count($in, '[/quote]')) {
$search[] = '~\[quote=(.+?)]~i';
$search[] = '~\[quote]~i';
$search[] = '~\[/quote]~i';
$replace[] = '<table style="width:90%; margin-left:5%; margin-right:5%;" border="0" cellpadding="3" cellspacing="0"><tr><td><b>\1 ' . $this->lang->main_said . ':</b></td></tr><tr><td class="quote">';
$replace[] = '<table style="width:90%; margin-left:5%; margin-right:5%;" border="0" cellpadding="3" cellspacing="0"><tr><td><b>' . $this->lang->main_quote . ':</b></td></tr><tr><td class="quote">';
$replace[] = '</td></tr></table>';
}
$in = preg_replace_callback($search, $replace, $in);
$in = str_replace(array(' ', "\t", '&#'), array(' ', ' ', '&#'), $in);
}
return $in;
}
我测试了将匿名函数直接放入替换数组的尝试,但收到错误消息:class 闭包的对象无法转换为字符串。但也许我做错了?
$replace = array(
'\1[email]\2[/email]',
"'\'\1[url]\'" . function (array $matches) {return wordwrap($matches[1], $matches[2], $matches[3], $matches[4]); } . " \'[/url]\''"
);
非常感谢您的建议。
创建一个关联数组,其中键包含正则表达式模式,值包含回调(回调没有 prepending/appending 字符串)。
我不会重写我的 phone 中的那个庞然大物,所以我将演示一个替换。
将您的模式和回调数组提供给 preg_replace_callback_array()
。
代码:(Demo)
$patternCallbacks = [
'~\[code](.*?)\[/code]~is' =>
function($m) {
return '[code]' . base64_encode($m[1]) . '[/code]';
},
// add more elements as needed...
];
echo preg_replace_callback_array(
$patternCallbacks,
'This is my [code]script[/code] to display'
);
输出:
This is my [code]c2NyaXB0[/code] to display
编辑,因为你不能使用preg_replace_callback_array()
,你需要重复调用preg_replace_callback()
。
代码:(Demo)
$patternCallbacks = [
'~\[code](.*?)\[/code]~is' =>
function($m) {
return '[code]' . base64_encode($m[1]) . '[/code]';
},
'~\[php(?:=\d+)?]\K(.*?)\[/php]~is' =>
function($m) {
return base64_encode($m[1]) . '[/php]';
},
];
$text = <<<TEXT
This is my [code]script[/code] to display.
It has [php]unnumbered tag
code[/php] and [php=8]numbered tag code[/php].'
TEXT;
foreach ($patternCallbacks as $pattern => $callback) {
$text = preg_replace_callback($pattern, $callback, $text);
}
echo $text;
输出:
This is my [code]c2NyaXB0[/code] to display.
It has [php]dW5udW1iZXJlZCB0YWcKIGNvZGU=[/php] and [php=8]bnVtYmVyZWQgdGFnIGNvZGU=[/php].