使用PHP将字符串内的花括号之间的子串提取到数组中

时间:2014-06-25 14:04:20

标签: php regex

我需要帮助来提取在特定字符串中找到的花括号之间的所有子字符串。

我在javascript中找到了一些解决方案,但我需要它用于PHP。

$string = "www.example.com/?foo={foo}&test={test}";
$subStrings = HELPME($string);
print_r($subStrings);

结果应为:

array( [0] => foo, [1] => test )

我尝试过玩preg_match,但我感到困惑。

如果有人设法让它与preg_match一起工作,我会感激,并解释它背后的逻辑是什么。

7 个答案:

答案 0 :(得分:5)

您可以使用此正则表达式捕获{}

之间的字符串
\{([^}]*)\}

<强>解释

  • \{匹配文字{
  • ([^}]*)捕获}以外的所有字符零次或多次。因此它会捕获下一个}符号。
  • \}匹配文字}

您的代码将是,

<?php
$regex = '~\{([^}]*)\}~'; 
$string = "www.example.com/?foo={foo}&test={test}";
preg_match_all($regex, $string, $matches);
var_dump($matches[1]);
?>

输出:

array(2) {
  [0]=>
  string(3) "foo"
  [1]=>
  string(4) "test"
}

DEMO

答案 1 :(得分:4)

正则表达式:\{(\w+)\}

获取括号()捕获的所有匹配项。该模式表示捕获{...}所包围的任何内容。

示例代码:

$regex = '/\{(\w{1,})\}/';
$testString = ''; // Fill this in
preg_match_all($regex, $testString, $matches);
// the $matches variable contains the list of matches

以下是debuggex

上的演示

如果你想捕捉{...}内的任何类型的角色,请尝试以下正则表达式模式。

正则表达式:\{(.*?)\}

示例代码:

$regex = '/\{(.{0,}?)\}/';
$testString = ''; // Fill this in
preg_match_all($regex, $testString, $matches);
// the $matches variable contains the list of matches

以下是debuggex

上的演示

答案 2 :(得分:2)

<?php
$string = "www.example.com/?foo={foo}&test={test}";
$found = preg_match('/\{([^}]*)\}/',$string, $subStrings);
if($found){
   print_r($subStrings);
}else{
    echo 'NOPE !!';
}

DEMO HERE

答案 3 :(得分:1)

函数parse_url,它解析URL并返回其组件。包括查询字符串。

答案 4 :(得分:1)

我在这里看到使用带有捕获组,环视和惰性量词的正则表达式的答案。所有这些技术都会减慢模式的速度-当然,在大多数用例中,性能都不太可能引起注意。因为我们打算提供的解决方案不仅仅只是发布的问题,所以我将提供一些解决方案,这些解决方案可以提供预期的结果,并使用分配给{{1}的OP的www.example.com/?foo={foo}&test={test}字符串来解释差异}。我已经准备好 a php DEMO of the techniques to follow 。有关函数调用的信息,请单击php手册的链接。要深入了解正则表达式模式,我建议使用regex101.com,这是一个免费的在线工具,可让您针对字符串测试模式,将结果既显示为突出显示的文本,又显示为分组列表,并提供技术击穿字符- regex引擎如何解释您的模式的各个字符。


#1因为您的输入字符串是url,所以非正则表达式技术是适当的,因为php具有解析它的本机功能:parse_url()parse_str()。不幸的是,您的要求不仅限于提取查询字符串的值,还希望re-index the arrayremove the curly braces from the values

$url

尽管这种方法是经过精心设计的,并且公平地使用了为这些工作而构建的本机函数,但最终却生成了更长,更复杂的代码,这在可读性方面有些令人不快。但是,它提供了所需的输出数组,应该被认为是可行的过程。


#2 preg_match_all()是一种超简短且高效的提取值的技术。使用正则表达式的一个缺点是,正则表达式引擎完全“不知道”格式化输入字符串可能具有的任何特殊含义。在这种情况下,我看不到任何负面影响,但是当出现打ic时,通常的解决方案是使用“格式/数据类型感知”解析器。

parse_str(parse_url($url, PHP_URL_QUERY), $assocArray);
$values = array_map(function($v) {return trim($v, '{}');}, array_values($assocArray));
var_export($values);

请注意,my pattern不需要捕获组或环视;我的答案也不会因为使用惰性量词而受苦。 var_export(preg_match_all('~\{\K[^}]*~', $url, $matches) ? $matches[0] : []); 用于“重新开始全字符串匹配”(换句话说,请忘记所有匹配的字符)。所有这些功能将意味着正则表达式引擎可以以最高效率遍历字符串。如果使用该功能有不利之处,那么它们是:

  • 只需要一维数组时,就会生成多维数组
  • 该函数创建引用变量而不是返回结果

#3 preg_split()与您的任务的纯英语意图最接近,并提供确切的输出作为其返回值。

\K

My pattern虽然对新手正则表达式模式设计者来说毫无用处,并且效率较低,因为它正在进行“分支”匹配(var_export(preg_split('~(?:(?:^|})[^{]*{)|}[^{]*$~', $url, 0, PREG_SPLIT_NO_EMPTY)); ),基本上说:“在以下定界符处分割字符串:

  • 从字符串的开头或|(包括所有非}字符)开始,然后是遇到的第一个{(这是定界符的结尾)。
  • li>
  • 从后{开始,包括所有非}字符,直到字符串末尾。”

答案 5 :(得分:0)

试试这个:

preg_match_all("/\{.*?\}/", $string, $subStrings);
var_dump($subStrings[0]);

祝你好运!

答案 6 :(得分:0)

您可以使用表达式(?<=\{).*?(?=\})来匹配{}中包含的任何文字字符串。

$string = "www.example.com/?foo={foo}&test={test}";
preg_match_all("/(?<=\{).*?(?=\})/",$string,$matches);
print_r($matches[0]);

正则表达式解释道:

(?<=\{)是一个积极的外观,断言文本行前面有一个{。 同样地,(?=\})是一个积极的先行者,声称它后跟一个}.*匹配任何类型的0个或多个字符。 ?中的.*?使其匹配尽可能少的字符数。 (意思是它与foo中的{foo} and {bar}匹配,而不是foo} and {bar

$matches[0]包含所有匹配字符串的数组。