[英]Extracting data from a template string
I need to get data from a string by a template.我需要通过模板从字符串中获取数据。 An example should make it clearer:
一个例子应该更清楚:
// What I have
$utterance = 'This is a brown bear with 7 kids';
$template = 'This is a {color} bear with {kids} kids';
// What I want
[
"color" => "brown",
"kids" => "7",
]
I have a very ugly solution to this:我对此有一个非常丑陋的解决方案:
$regex = '/' . preg_replace('/{.*?}/' , '.*?', $template) . '/i';
foreach(preg_split('/\{.*?\}/', $template) as $part) {
$utterance = str_replace($part, Str::startsWith($template, $part) || Str::endsWith($template, $part) ? '' : '|', $utterance);
}
preg_match_all('/{(.*?)}/', $template, $variables);
$values = explode('|', $utterance);
$variables = $variables[1];
array_combine($variables, $values);
Does anyone have a nicer way of doing this?有没有人有更好的方法来做到这一点? Seems like an ugly approach...
似乎是一个丑陋的方法......
I would go with something like this, first you will explode template, then foreach that array and find words which starts with {, when u find such you know index of the word so you can try to find same index in exploded utterance.我会用类似这样的东西 go ,首先你会分解模板,然后 foreach 那个数组并找到以 { 开头的单词,当你找到这样的你知道单词的索引,所以你可以尝试在分解的话语中找到相同的索引。
<?php
$utterance = 'This is a brown bear with 7 kids';
$template = 'This is a {color} bear with {kids} kids';
$utter_words = explode(" ",$utterance);
$temp_words = explode(" ",$template);
$output = array();
foreach($temp_words as $i=>$temp_word){
if(strpos($temp_word, "{")===0){
$key = str_replace(array("{","}"), "", $temp_word);
$output[$key] = $utter_words[$i];
}
}
var_dump($output);
output output
array(2) {
["color"]=>
string(5) "brown"
["kids"]=>
string(1) "7"
}
Try this code试试这个代码
$utterance = 'This is a brown bear with 7 kids';
$template = '/This is a (.*?) bear with (.*?) kids/';
preg_match($template, $utterance, $m);
print_r($m);
echo "color = ".$m[1].PHP_EOL;
echo "kids = ".$m[2].PHP_EOL;
output output
Array
(
[0] => This is a brown bear with 7 kids
[1] => brown
[2] => 7
)
color = brown
kids = 7
You can convert your template into a regular expression which uses "named captures", which look like (?<name>pattern)
您可以将模板转换为使用“命名捕获”的正则表达式,看起来像
(?<name>pattern)
In your example, the template 'This is a {color} bear with {kids} kids'
can become '/This is a (?<color>.*?) bear with (?<kids>.*?) kids/'
在您的示例中,模板
'This is a {color} bear with {kids} kids'
可以变成'/This is a (?<color>.*?) bear with (?<kids>.*?) kids/'
To generate that, you use a different regular expression to find all the placeholders - /\{(.*?)\}/
- and a replacement string using the back-reference \1
- (?<\1>.*?)
要生成它,您使用不同的正则表达式来查找所有占位符 -
/\{(.*?)\}/
- 并使用反向引用\1
- (?<\1>.*?)
替换字符串
Then you match the final regex against the utterance, and the named matches will show up in the by-reference matches array:然后将最终的正则表达式与话语进行匹配,命名的匹配项将显示在按引用匹配数组中:
$utterance = 'This is a brown bear with 7 kids';
$template = 'This is a {color} bear with {kids} kids';
$templateRegex = '/' . preg_replace('/\{(.*?)\}/', '(?<\1>.*?)', $template) . '/';
$matches = [];
preg_match($templateRegex, $utterance, $matches);
var_dump($matches);
Gives:给出:
array(5) {
[0]=>
string(32) "This is a brown bear with 7 kids"
["color"]=>
string(5) "brown"
[1]=>
string(5) "brown"
["kids"]=>
string(1) "7"
[2]=>
string(1) "7"
}
So $matches['color']
is 'brown'
.所以
$matches['color']
是'brown'
。 You can filter out the numeric offsets which you don't want, and you'll just have the key-value list you wanted.你可以过滤掉你不想要的数字偏移量,你就会得到你想要的键值列表。
Note that you may need to do some extra preparation on your string using preg_quote to make sure everything other than the placeholders is matched literally.请注意,您可能需要使用preg_quote对字符串做一些额外的准备,以确保除占位符之外的所有内容都按字面意思匹配。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.