关于php:在字符串中替换占位符变量

4,058次阅读
2 条评论

Replacing Placeholder Variables in a String

刚完成此功能。 基本上,假设要遍历一个字符串并尝试找到任何占位符变量,这些变量将位于两个大括号{}之间。 它获取大括号之间的值,并使用它查看应与键匹配的数组。 然后,它将字符串中的花括号变量替换为匹配键数组中的值。

但是它有一些问题。 首先是当我var_dump($matches)时,将结果放入数组中的数组中。 因此,我必须使用两个foreach()才能达到正确的数据。

我也觉得它很重,我一直在寻找它,试图使其变得更好,但我有些沮丧。 我错过了任何优化吗?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function dynStr($str,$vars) {
 preg_match_all(“/\{[A-Z0-9_]+\}+/”, $str, $matches);
 foreach($matches as $match_group) {
 foreach($match_group as $match) {
 $match = str_replace(“}”,””, $match);
 $match = str_replace(“{“,””, $match);
 $match = strtolower($match);
 $allowed = array_keys($vars);
 $match_up = strtoupper($match);
 $str = (in_array($match, $allowed)) ? str_replace(“{“.$match_up.”}”, $vars[$match], $str) : str_replace(“{“.$match_up.”}”, ”, $str);
 }
 }
 return $str;
}$variables = array(“first_name”=>”John”,”last_name”=>”Smith”,”status”=>”won”);
$string = ‘Dear {FIRST_NAME} {LAST_NAME}, we wanted to tell you that you {STATUS} the competition.’;
echo dynStr($string,$variables);
//Would output: ‘Dear John Smith, we wanted to tell you that you won the competition.’

 相关讨论

  • 请向我们提供数据样本($ str和$ vars)
  • 您的方法效率很低。考虑另一种方法:a)使用preg_replace_callback从$vars返回匹配的令牌值,而无需进行一百万次str_replace调用; b)转换$vars中的每个条目以包括前导/后括号,然后将$vars馈入strtr。
  • 您是作为学习练习还是为生产而做的?如果用于生产,您可能想要查看类似smarty的模板库
  • @DCoder:您能提供一些例子吗?我对你说的话感到困惑。
  • @ dm03514供生产使用,但就像初稿一样。不是最终产品。它也不是模板。它是新闻通讯。
  • @TylerDusty:我的第一个建议与下面发布的fireeyedboy相同。
  • @TylerDusty smarty是一个模板库,旨在完全满足您的需求,但是smarty是一个大型成熟项目。它现在就可以使用,并且可以处理项目开发过程中遇到的所有疯狂情况,而且它既快速又可靠。

我认为对于这样一个简单的任务,您无需使用RegEx:

1
2
3
4
5
6
7
8
$variables = array(“first_name”=>”John”,”last_name”=>”Smith”,”status”=>”won”);
$string = ‘Dear {FIRST_NAME} {LAST_NAME}, we wanted to tell you that you {STATUS} the competition.’;foreach($variables as $key => $value){
 $string = str_replace(‘{‘.strtoupper($key).’}’, $value, $string);
}echo $string; // Dear John Smith, we wanted to tell you that you won the competition.

 相关讨论

  • 实际上,这甚至比我的答案还要简单,甚至可能足够。
  • 哇,是的我想我们都考虑得太多了。不良运行一些测试,看是否更快,并告知您。足够。
  • @fireeyedboy我喜欢您的preg_replace_callback()解决方案,我试图弄清楚如何使用匿名函数以及如何在范围内包含$allowed变量,然后我看到了您的答案。 +1:D
  • @HamZaDzCyber??DeV我太挂了,想变得漂亮,以至于没有想到像您这样的解决方案。有时先退后一步会有所帮助。我对您的解决方案只发生了一点小小的警告,那就是它不利于从输入字符串中删除无效的占位符(但这并不是开始时的要求)。
  • 提示:str_replace可以使用字符串数组来查找/替换。一个str_replace呼叫可能会快于一百。
  • @DCoder是的,您是对的,这里的问题是$variables中的键不能以正确的格式(用{}和大写字母包围)。

我希望我加入该聚会还为时不晚-这是我的工作方式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function template_substitution($template, $data) {
 $placeholders = array_keys($data);
 foreach ($placeholders as &$placeholder) {
 $placeholder = strtoupper(“{{$placeholder}}”);
 }
 return str_replace($placeholders, array_values($data), $template);
}$variables = array(
 ‘first_name’ => ‘John’,
 ‘last_name’ => ‘Smith’,
 ‘status’ => ‘won’,
);$string = ‘Dear {FIRST_NAME} {LAST_NAME}, we wanted to tell you that you have {STATUS} the competition.’;echo template_substitution($string, $variables);

而且,只要有机会使您的$variables键与占位符完全匹配,解决方案就变得非常简单:

1
2
3
4
5
6
7
8
9
$variables = array(
 ‘{FIRST_NAME}’ => ‘John’,
 ‘{LAST_NAME}’ => ‘Smith’,
 ‘{STATUS}’ => ‘won’,
);$string = ‘Dear {FIRST_NAME} {LAST_NAME}, we wanted to tell you that you have {STATUS} the competition.’;echo strtr($string, $variables);

(请参阅PHP手册中的strtr()。)

考虑到PHP语言的性质,我认为这种方法应该在该线程中列出的所有方法中产生最佳性能。

 相关讨论

  • 我同意-除了性能,这也是最具可读性和可维护性的恕我直言。我对另一个问题的回答(stackoverflow.com/a/36781566/224707)也显示了此方法的其他优点,例如能够在处理之前以编程方式增强替换值(例如对它们进行编码或主题化)…

我认为您可以通过以下方式大大简化您的代码(除非我误解了一些要求):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$allowed = array(“first_name”=>”John”,”last_name”=>”Smith”,”status”=>”won”);$resultString = preg_replace_callback// the pattern, no need to escape curly brackets
 // uses a group (the parentheses) that will be captured in $matches[ 1 ]
 ‘/{([A-Z0-9_]+)}/’, // the callback, uses $allowed array of possible variables
 function( $matches ) use ( $allowed )
 {
 $key = strtolower( $matches[ 1 ] );
 // return the complete match (captures in $matches[ 0 ]) if no allowed value is found
 return array_key_exists( $key, $allowed ) ? $allowed[ $key ] : $matches[ 0 ];
 }, // the input string
 $yourString
);

PS .:如果要删除输入字符串中不允许的占位符,请替换

1 return array_key_exists( $key, $allowed ) ? $allowed[ $key ] : $matches[ 0 ];

1 return array_key_exists( $key, $allowed ) ? $allowed[ $key ] : ”;

 相关讨论

  • 看起来可能更好,但是我对function( $matches ) use ( $allowed )是什么感到好奇吗?我从来没有见过使用,我的代码编辑器(dreamweaver)说它不正确。
  • @TylerDusty:其匿名函数,需要PHP 5.3。
  • @TylerDusty回调是一个闭包。 use构造用于从定义范围导入变量,以便可以在闭包内部使用它。确实,正如DCoder已经提到的那样,它具有PHP 5.3+功能。

只是提醒将来进入此页面的人:使用foreach循环和/或str_replace方法的所有答案(包括接受的答案)都容易用OL’Johnny {STATUS}的名字替换Johnny won。

我看到,目前发布的仅有的几个方法不错,如Decent Dabbler的preg_replace_callback方法和U-D13的第二个选项(但不是第一个),对此并不容易,但是由于我没有足够的声誉来添加评论,因此我想就是写一个完全不同的答案。

如果替换值包含用户输入,则一种更安全的解决方案是使用strtr函数而不是str_replace以避免重新替换可能出现在您的值中的任何占位符。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$string = ‘Dear {FIRST_NAME} {LAST_NAME}, we wanted to tell you that you {STATUS} the competition.’;
$variables = array(
“first_name”=>”John”,
 // Note the value here
“last_name”=>”{STATUS}”,
“status”=>”won”
);// bonus one-liner for transforming the placeholders
// but it’s ugly enough I broke it up into multiple lines anyway :)
$replacement = array_combine(
 array_map(function($k) { return ‘{‘.strtoupper($k).’}’; }, array_keys($variables)),
 array_values($variables)
);echo strtr($string, $replacement);

输出:Dear John {STATUS}, we wanted to tell you that you won the competition.
而str_replace输出:Dear John won, we wanted to tell you that you won the competition.

 相关讨论

  • strtr()是此问题的正确答案。

这是我使用的功能:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
function searchAndReplace($search, $replace){
 preg_match_all(“/\{(.+?)\}/”, $search, $matches); if (isset($matches[1]) && count($matches[1]) > 0){
 foreach ($matches[1] as $key => $value) {
 if (array_key_exists($value, $replace)){
 $search = preg_replace(“/\{$value\}/”, $replace[$value], $search);
 }
 }
 }
 return $search;
}$array = array(
‘FIRST_NAME’ => ‘John’,
‘LAST_NAME’ => ‘Smith’,
‘STATUS’ => ‘won’
);$paragraph = ‘Dear {FIRST_NAME} {LAST_NAME}, we wanted to tell you that you {STATUS} the competition.’;// outputs: Dear John Smith, we wanted to tell you that you won the competition.

只需将其传递一些文本来进行搜索,然后输入包含替换项的数组即可。


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/**
   replace placeholders with object
**/

$user = new stdClass();
$user->first_name = ‘Nick’;
$user->last_name = ‘Trom’;$message = ‘This is a {{first_name}} of a user. The user\’s {{first_name}} is replaced as well as the user\’s {{last_name}}.’;preg_match_all(‘/{{([0-9A-Za-z_]+)}}/’, $message, $matches);foreach($matches[1] as $match)
{
 if(isset($user->$match))
 $rep = $user->$match;
 else
 $rep = ”; $message = str_replace(‘{{‘.$match.’}}’, $rep, $message);
}echo $message;
正文完
可以使用微信扫码关注公众号(ID:xzluomor)
post-qrcode
 0
评论(2 条评论)
2024-04-25 19:32:55 回复

Very well presented. Every quote was awesome and thanks for sharing the content. Keep sharing and keep motivating others.

     泰国
2024-07-17 04:33:20 回复

มีเกมให้เลือกเล่นมากมาย: เกมเดิมพันหลากหลาย ครบทุกค่ายดัง

     美国新泽西

文心AIGC

2023 年 11 月
 12345
6789101112
13141516171819
20212223242526
27282930  
文心AIGC
文心AIGC
人工智能ChatGPT,AIGC指利用人工智能技术来生成内容,其中包括文字、语音、代码、图像、视频、机器人动作等等。被认为是继PGC、UGC之后的新型内容创作方式。AIGC作为元宇宙的新方向,近几年迭代速度呈现指数级爆发,谷歌、Meta、百度等平台型巨头持续布局
文章搜索
热门文章
清库存!DeepSeek突然补全R1技术报告,训练路径首次详细公开

清库存!DeepSeek突然补全R1技术报告,训练路径首次详细公开

清库存!DeepSeek突然补全R1技术报告,训练路径首次详细公开 Jay 2026-01-08 20:18:...
训具身模型遇到的很多问题,在数据采集时就已经注定了丨鹿明联席CTO丁琰分享

训具身模型遇到的很多问题,在数据采集时就已经注定了丨鹿明联席CTO丁琰分享

训具身模型遇到的很多问题,在数据采集时就已经注定了丨鹿明联席CTO丁琰分享 衡宇 2026-01-08 20:...
开源“裸考”真实世界,国产具身智能基座模型拿下全球第二!

开源“裸考”真实世界,国产具身智能基座模型拿下全球第二!

开源“裸考”真实世界,国产具身智能基座模型拿下全球第二! 西风 2026-01-08 19:02:20 来源:...
「北京版幻方」冷不丁开源SOTA代码大模型!一张3090就能跑,40B参数掀翻Opus-4.5和GPT-5.2

「北京版幻方」冷不丁开源SOTA代码大模型!一张3090就能跑,40B参数掀翻Opus-4.5和GPT-5.2

「北京版幻方」冷不丁开源SOTA代码大模型!一张3090就能跑,40B参数掀翻Opus-4.5和GPT-5.2...
最新评论
ufabet ufabet มีเกมให้เลือกเล่นมากมาย: เกมเดิมพันหลากหลาย ครบทุกค่ายดัง
tornado crypto mixer tornado crypto mixer Discover the power of privacy with TornadoCash! Learn how this decentralized mixer ensures your transactions remain confidential.
ดูบอลสด ดูบอลสด Very well presented. Every quote was awesome and thanks for sharing the content. Keep sharing and keep motivating others.
ดูบอลสด ดูบอลสด Pretty! This has been a really wonderful post. Many thanks for providing these details.
ดูบอลสด ดูบอลสด Pretty! This has been a really wonderful post. Many thanks for providing these details.
ดูบอลสด ดูบอลสด Hi there to all, for the reason that I am genuinely keen of reading this website’s post to be updated on a regular basis. It carries pleasant stuff.
Obrazy Sztuka Nowoczesna Obrazy Sztuka Nowoczesna Thank you for this wonderful contribution to the topic. Your ability to explain complex ideas simply is admirable.
ufabet ufabet Hi there to all, for the reason that I am genuinely keen of reading this website’s post to be updated on a regular basis. It carries pleasant stuff.
ufabet ufabet You’re so awesome! I don’t believe I have read a single thing like that before. So great to find someone with some original thoughts on this topic. Really.. thank you for starting this up. This website is something that is needed on the internet, someone with a little originality!
ufabet ufabet Very well presented. Every quote was awesome and thanks for sharing the content. Keep sharing and keep motivating others.
热评文章
首家央企AI独角兽浮出水面!背靠自研大模型,4家国家队资本背书

首家央企AI独角兽浮出水面!背靠自研大模型,4家国家队资本背书

首家央企AI独角兽浮出水面!背靠自研大模型,4家国家队资本背书 Jay 2026-01-07 15:24:04...
悲报!Stack Overflow彻底凉了,比18年前上线首月问题数量还少

悲报!Stack Overflow彻底凉了,比18年前上线首月问题数量还少

悲报!Stack Overflow彻底凉了,比18年前上线首月问题数量还少 闻乐 2026-01-05 19:...
老黄All in物理AI!最新GPU性能5倍提升,还砸掉了智驾门槛

老黄All in物理AI!最新GPU性能5倍提升,还砸掉了智驾门槛

老黄All in物理AI!最新GPU性能5倍提升,还砸掉了智驾门槛 闻乐 2026-01-06 09:09:0...
OpenAI推理第一人离职,7年打造了o3/o1/GPT-4/Codex

OpenAI推理第一人离职,7年打造了o3/o1/GPT-4/Codex

OpenAI推理第一人离职,7年打造了o3/o1/GPT-4/Codex 衡宇 2026-01-06 13:0...
OpenAI推理第一人离职,7年打造了o3/o1/GPT-4/Codex

OpenAI推理第一人离职,7年打造了o3/o1/GPT-4/Codex

OpenAI推理第一人离职,7年打造了o3/o1/GPT-4/Codex 衡宇 2026-01-06 13:0...