简体   繁体   English

从模板字符串中提取数据

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM